C语言数据结构之单链表存储实例分析

发布时间:2022-07-27 13:43:18 作者:iii
来源:亿速云 阅读:146

C语言数据结构之单链表存储实例分析

目录

  1. 引言
  2. 单链表的基本概念
  3. 单链表的存储结构
  4. 单链表的基本操作
  5. 单链表的应用实例
  6. 单链表的优缺点
  7. 总结

引言

在计算机科学中,数据结构是组织和存储数据的方式,以便能够高效地访问和修改数据。单链表是一种常见的数据结构,广泛应用于各种编程场景中。本文将详细介绍单链表的基本概念、存储结构、基本操作以及应用实例,并通过C语言代码示例进行深入分析。

单链表的基本概念

单链表(Singly Linked List)是一种线性数据结构,由一系列节点组成,每个节点包含两个部分:数据域和指针域。数据域用于存储数据,指针域用于指向下一个节点。单链表的特点是只能单向遍历,即从头节点开始,依次访问每个节点,直到尾节点。

单链表的存储结构

单链表的存储结构可以用C语言中的结构体来表示。每个节点包含一个数据域和一个指向下一个节点的指针。以下是一个简单的单链表节点结构体定义:

struct Node {
    int data;           // 数据域
    struct Node* next;  // 指针域,指向下一个节点
};

单链表的基本操作

创建单链表

创建单链表的过程包括初始化头节点和添加后续节点。以下是一个创建单链表的C语言代码示例:

#include <stdio.h>
#include <stdlib.h>

struct Node {
    int data;
    struct Node* next;
};

// 创建单链表
struct Node* createLinkedList(int arr[], int n) {
    struct Node *head = NULL, *temp = NULL, *current = NULL;

    for (int i = 0; i < n; i++) {
        temp = (struct Node*)malloc(sizeof(struct Node));
        temp->data = arr[i];
        temp->next = NULL;

        if (head == NULL) {
            head = temp;
        } else {
            current->next = temp;
        }
        current = temp;
    }

    return head;
}

// 打印单链表
void printLinkedList(struct Node* head) {
    struct Node* current = head;
    while (current != NULL) {
        printf("%d -> ", current->data);
        current = current->next;
    }
    printf("NULL\n");
}

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int n = sizeof(arr) / sizeof(arr[0]);

    struct Node* head = createLinkedList(arr, n);
    printLinkedList(head);

    return 0;
}

插入节点

在单链表中插入节点可以分为三种情况:在链表头部插入、在链表尾部插入和在链表中间插入。以下是一个在单链表中插入节点的C语言代码示例:

// 在链表头部插入节点
struct Node* insertAtHead(struct Node* head, int data) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = data;
    newNode->next = head;
    return newNode;
}

// 在链表尾部插入节点
struct Node* insertAtTail(struct Node* head, int data) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = data;
    newNode->next = NULL;

    if (head == NULL) {
        return newNode;
    }

    struct Node* current = head;
    while (current->next != NULL) {
        current = current->next;
    }
    current->next = newNode;

    return head;
}

// 在链表中间插入节点
struct Node* insertAtMiddle(struct Node* head, int data, int position) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = data;

    if (position == 0) {
        newNode->next = head;
        return newNode;
    }

    struct Node* current = head;
    for (int i = 0; i < position - 1 && current != NULL; i++) {
        current = current->next;
    }

    if (current == NULL) {
        printf("Position out of range\n");
        return head;
    }

    newNode->next = current->next;
    current->next = newNode;

    return head;
}

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int n = sizeof(arr) / sizeof(arr[0]);

    struct Node* head = createLinkedList(arr, n);
    printLinkedList(head);

    head = insertAtHead(head, 0);
    printLinkedList(head);

    head = insertAtTail(head, 6);
    printLinkedList(head);

    head = insertAtMiddle(head, 7, 3);
    printLinkedList(head);

    return 0;
}

删除节点

在单链表中删除节点可以分为三种情况:删除头节点、删除尾节点和删除中间节点。以下是一个在单链表中删除节点的C语言代码示例:

// 删除头节点
struct Node* deleteAtHead(struct Node* head) {
    if (head == NULL) {
        printf("List is empty\n");
        return NULL;
    }

    struct Node* temp = head;
    head = head->next;
    free(temp);

    return head;
}

// 删除尾节点
struct Node* deleteAtTail(struct Node* head) {
    if (head == NULL) {
        printf("List is empty\n");
        return NULL;
    }

    if (head->next == NULL) {
        free(head);
        return NULL;
    }

    struct Node* current = head;
    while (current->next->next != NULL) {
        current = current->next;
    }

    free(current->next);
    current->next = NULL;

    return head;
}

// 删除中间节点
struct Node* deleteAtMiddle(struct Node* head, int position) {
    if (head == NULL) {
        printf("List is empty\n");
        return NULL;
    }

    if (position == 0) {
        struct Node* temp = head;
        head = head->next;
        free(temp);
        return head;
    }

    struct Node* current = head;
    for (int i = 0; i < position - 1 && current != NULL; i++) {
        current = current->next;
    }

    if (current == NULL || current->next == NULL) {
        printf("Position out of range\n");
        return head;
    }

    struct Node* temp = current->next;
    current->next = current->next->next;
    free(temp);

    return head;
}

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int n = sizeof(arr) / sizeof(arr[0]);

    struct Node* head = createLinkedList(arr, n);
    printLinkedList(head);

    head = deleteAtHead(head);
    printLinkedList(head);

    head = deleteAtTail(head);
    printLinkedList(head);

    head = deleteAtMiddle(head, 1);
    printLinkedList(head);

    return 0;
}

查找节点

在单链表中查找节点可以通过遍历链表来实现。以下是一个在单链表中查找节点的C语言代码示例:

// 查找节点
struct Node* searchNode(struct Node* head, int data) {
    struct Node* current = head;
    while (current != NULL) {
        if (current->data == data) {
            return current;
        }
        current = current->next;
    }
    return NULL;
}

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int n = sizeof(arr) / sizeof(arr[0]);

    struct Node* head = createLinkedList(arr, n);
    printLinkedList(head);

    struct Node* result = searchNode(head, 3);
    if (result != NULL) {
        printf("Node found: %d\n", result->data);
    } else {
        printf("Node not found\n");
    }

    return 0;
}

遍历单链表

遍历单链表是指依次访问链表中的每个节点,并对其进行操作。以下是一个遍历单链表的C语言代码示例:

// 遍历单链表
void traverseLinkedList(struct Node* head) {
    struct Node* current = head;
    while (current != NULL) {
        printf("%d -> ", current->data);
        current = current->next;
    }
    printf("NULL\n");
}

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int n = sizeof(arr) / sizeof(arr[0]);

    struct Node* head = createLinkedList(arr, n);
    traverseLinkedList(head);

    return 0;
}

单链表的应用实例

学生信息管理系统

单链表可以用于实现学生信息管理系统。以下是一个简单的学生信息管理系统的C语言代码示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Student {
    int id;
    char name[50];
    float grade;
    struct Student* next;
};

// 创建学生信息链表
struct Student* createStudentList(int ids[], char names[][50], float grades[], int n) {
    struct Student *head = NULL, *temp = NULL, *current = NULL;

    for (int i = 0; i < n; i++) {
        temp = (struct Student*)malloc(sizeof(struct Student));
        temp->id = ids[i];
        strcpy(temp->name, names[i]);
        temp->grade = grades[i];
        temp->next = NULL;

        if (head == NULL) {
            head = temp;
        } else {
            current->next = temp;
        }
        current = temp;
    }

    return head;
}

// 打印学生信息链表
void printStudentList(struct Student* head) {
    struct Student* current = head;
    while (current != NULL) {
        printf("ID: %d, Name: %s, Grade: %.2f\n", current->id, current->name, current->grade);
        current = current->next;
    }
}

// 插入学生信息
struct Student* insertStudent(struct Student* head, int id, char name[], float grade) {
    struct Student* newNode = (struct Student*)malloc(sizeof(struct Student));
    newNode->id = id;
    strcpy(newNode->name, name);
    newNode->grade = grade;
    newNode->next = head;
    return newNode;
}

// 删除学生信息
struct Student* deleteStudent(struct Student* head, int id) {
    struct Student* current = head;
    struct Student* previous = NULL;

    while (current != NULL && current->id != id) {
        previous = current;
        current = current->next;
    }

    if (current == NULL) {
        printf("Student with ID %d not found\n", id);
        return head;
    }

    if (previous == NULL) {
        head = current->next;
    } else {
        previous->next = current->next;
    }

    free(current);
    return head;
}

// 查找学生信息
struct Student* searchStudent(struct Student* head, int id) {
    struct Student* current = head;
    while (current != NULL) {
        if (current->id == id) {
            return current;
        }
        current = current->next;
    }
    return NULL;
}

int main() {
    int ids[] = {1, 2, 3};
    char names[][50] = {"Alice", "Bob", "Charlie"};
    float grades[] = {85.5, 90.0, 78.5};
    int n = sizeof(ids) / sizeof(ids[0]);

    struct Student* head = createStudentList(ids, names, grades, n);
    printStudentList(head);

    head = insertStudent(head, 4, "David", 88.0);
    printStudentList(head);

    head = deleteStudent(head, 2);
    printStudentList(head);

    struct Student* result = searchStudent(head, 3);
    if (result != NULL) {
        printf("Student found: ID: %d, Name: %s, Grade: %.2f\n", result->id, result->name, result->grade);
    } else {
        printf("Student not found\n");
    }

    return 0;
}

单链表的优缺点

优点

  1. 动态内存分配:单链表可以根据需要动态分配内存,避免了静态数组的固定大小限制。
  2. 插入和删除操作高效:在单链表中插入和删除节点的时间复杂度为O(1),尤其是在链表头部进行操作时。
  3. 灵活性:单链表可以轻松地扩展和缩减,适用于频繁插入和删除操作的场景。

缺点

  1. 访问效率低:单链表只能单向遍历,访问某个节点需要从头节点开始依次查找,时间复杂度为O(n)。
  2. 内存开销大:每个节点需要额外的指针域来存储下一个节点的地址,增加了内存开销。
  3. 不支持随机访问:单链表不支持像数组那样的随机访问,只能顺序访问。

总结

单链表是一种简单而灵活的数据结构,适用于需要频繁插入和删除操作的场景。通过本文的介绍,我们了解了单链表的基本概念、存储结构、基本操作以及应用实例。虽然单链表在某些方面存在不足,但其动态内存分配和高效插入删除操作的优点使其在许多实际应用中仍然具有重要价值。希望本文能够帮助读者更好地理解和应用单链表这一数据结构。

推荐阅读:
  1. 【C语言数据结构】循环单链表
  2. 【C语言数据结构】静态单链表

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

c语言

上一篇:怎么使用php编写守护进程

下一篇:Vue如何实现监听某个元素滚动

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》