C语言链表实现
C语言链表实现

单链表

单链表是最基本的链表,每个节点包含一个数据域和一个指向下一个节点的指针。

  1#include <stdio.h>
  2#include <stdlib.h>
  3
  4// 单链表节点定义
  5struct SinglyNode {
  6    int data;
  7    struct SinglyNode* next;
  8};
  9
 10// 创建新单链表节点
 11struct SinglyNode* createSinglyNode(int data) {
 12    struct SinglyNode* newNode = (struct SinglyNode*)malloc(sizeof(struct SinglyNode));
 13    newNode->data = data;
 14    newNode->next = NULL;
 15    return newNode;
 16}
 17
 18// 在单链表头部插入节点
 19void insertAtHeadSingly(struct SinglyNode** head, int data) {
 20    struct SinglyNode* newNode = createSinglyNode(data);
 21    newNode->next = *head;
 22    *head = newNode;
 23}
 24
 25// 在单链表尾部插入节点
 26void insertAtTailSingly(struct SinglyNode** head, int data) {
 27    struct SinglyNode* newNode = createSinglyNode(data);
 28    if (*head == NULL) {
 29        *head = newNode;
 30        return;
 31    }
 32
 33    struct SinglyNode* temp = *head;
 34    while (temp->next != NULL) {
 35        temp = temp->next;
 36    }
 37    temp->next = newNode;
 38}
 39
 40// 在单链表的指定位置插入节点
 41void insertAtPositionSingly(struct SinglyNode** head, int data, int position) {
 42    if (position == 1) {
 43        insertAtHeadSingly(head, data);
 44        return;
 45    }
 46
 47    struct SinglyNode* newNode = createSinglyNode(data);
 48    struct SinglyNode* temp = *head;
 49
 50    for (int i = 1; i < position - 1 && temp != NULL; i++) {
 51        temp = temp->next;
 52    }
 53
 54    if (temp == NULL) {
 55        printf("位置超出链表长度\n");
 56        return;
 57    }
 58
 59    newNode->next = temp->next;
 60    temp->next = newNode;
 61}
 62
 63// 删除单链表头部节点
 64void deleteHeadSingly(struct SinglyNode** head) {
 65    if (*head == NULL) return;
 66
 67    struct SinglyNode* temp = *head;
 68    *head = (*head)->next;
 69    free(temp);
 70}
 71
 72// 删除单链表尾部节点
 73void deleteTailSingly(struct SinglyNode** head) {
 74    if (*head == NULL) return;
 75
 76    if ((*head)->next == NULL) {
 77        free(*head);
 78        *head = NULL;
 79        return;
 80    }
 81
 82    struct SinglyNode* temp = *head;
 83    while (temp->next->next != NULL) {
 84        temp = temp->next;
 85    }
 86
 87    free(temp->next);
 88    temp->next = NULL;
 89}
 90
 91// 删除单链表的指定位置节点
 92void deleteAtPositionSingly(struct SinglyNode** head, int position) {
 93    if (*head == NULL) return;
 94
 95    if (position == 1) {
 96        deleteHeadSingly(head);
 97        return;
 98    }
 99
100    struct SinglyNode* temp = *head;
101    for (int i = 1; i < position - 1 && temp->next != NULL; i++) {
102        temp = temp->next;
103    }
104
105    if (temp->next == NULL) {
106        printf("位置超出链表长度\n");
107        return;
108    }
109
110    struct SinglyNode* nodeToDelete = temp->next;
111    temp->next = temp->next->next;
112    free(nodeToDelete);
113}
114
115// 打印单链表
116void printSinglyList(struct SinglyNode* head) {
117    struct SinglyNode* current = head;
118    while (current != NULL) {
119        printf("%d -> ", current->data);
120        current = current->next;
121    }
122    printf("NULL\n");
123}

双链表

双链表中的每个节点都包含两个指针,一个指向下一个节点,另一个指向前一个节点,这使得我们可以在两个方向上遍历链表。

  1// 双链表节点定义
  2struct DoublyNode {
  3    int data;
  4    struct DoublyNode* next;
  5    struct DoublyNode* prev;
  6};
  7
  8// 创建新双链表节点
  9struct DoublyNode* createDoublyNode(int data) {
 10    struct DoublyNode* newNode = (struct DoublyNode*)malloc(sizeof(struct DoublyNode));
 11    newNode->data = data;
 12    newNode->next = NULL;
 13    newNode->prev = NULL;
 14    return newNode;
 15}
 16
 17// 在双链表头部插入节点
 18void insertAtHeadDoubly(struct DoublyNode** head, int data) {
 19    struct DoublyNode* newNode = createDoublyNode(data);
 20    newNode->next = *head;
 21    if (*head != NULL) {
 22        (*head)->prev = newNode;
 23    }
 24    *head = newNode;
 25}
 26
 27// 在双链表尾部插入节点
 28void insertAtTailDoubly(struct DoublyNode** head, int data) {
 29    struct DoublyNode* newNode = createDoublyNode(data);
 30    if (*head == NULL) {
 31        *head = newNode;
 32        return;
 33    }
 34
 35    struct DoublyNode* temp = *head;
 36    while (temp->next != NULL) {
 37        temp = temp->next;
 38    }
 39    temp->next = newNode;
 40    newNode->prev = temp;
 41}
 42
 43// 在双链表的指定位置插入节点
 44void insertAtPositionDoubly(struct DoublyNode** head, int data, int position) {
 45    if (position == 1) {
 46        insertAtHeadDoubly(head, data);
 47        return;
 48    }
 49
 50    struct DoublyNode* newNode = createDoublyNode(data);
 51    struct DoublyNode* temp = *head;
 52
 53    for (int i = 1; i < position - 1 && temp != NULL; i++) {
 54        temp = temp->next;
 55    }
 56
 57    if (temp == NULL) {
 58        printf("位置超出链表长度\n");
 59        return;
 60    }
 61
 62    newNode->next = temp->next;
 63    if (temp->next != NULL) {
 64        temp->next->prev = newNode;
 65    }
 66    newNode->prev = temp;
 67    temp->next = newNode;
 68}
 69
 70// 删除双链表头部节点
 71void deleteHeadDoubly(struct DoublyNode** head) {
 72    if (*head == NULL) return;
 73
 74    struct DoublyNode* temp = *head;
 75    *head = (*head)->next;
 76
 77    if (*head != NULL) {
 78        (*head)->prev = NULL;
 79    }
 80
 81    free(temp);
 82}
 83
 84// 删除双链表尾部节点
 85void deleteTailDoubly(struct DoublyNode** head) {
 86    if (*head == NULL) return;
 87
 88    if ((*head)->next == NULL) {
 89        free(*head);
 90        *head = NULL;
 91        return;
 92    }
 93
 94    struct DoublyNode* temp = *head;
 95    while (temp->next != NULL) {
 96        temp = temp->next;
 97    }
 98
 99    temp->prev->next = NULL;
100    free(temp);
101}
102
103// 删除双链表的指定位置节点
104void deleteAtPositionDoubly(struct DoublyNode** head, int position) {
105    if (*head == NULL) return;
106
107    if (position == 1) {
108        deleteHeadDoubly(head);
109        return;
110    }
111
112    struct DoublyNode* temp = *head;
113    for (int i = 1; i < position && temp != NULL; i++) {
114        temp = temp->next;
115    }
116
117    if (temp == NULL) {
118        printf("位置超出链表长度\n");
119        return;
120    }
121
122    if (temp->next != NULL) {
123        temp->next->prev = temp->prev;
124    }
125    if (temp->prev != NULL) {
126        temp->prev->next = temp->next;
127    }
128
129    free(temp);
130}
131
132// 打印双链表
133void printDoublyList(struct DoublyNode* head) {
134    struct DoublyNode* current = head;
135    while (current != NULL) {
136        printf("%d <-> ", current->data);
137        current = current->next;
138    }
139    printf("NULL\n");
140}

循环单链表

循环链表的最后一个节点指向链表的头节点,从而形成一个循环结构。

  1// 循环链表节点定义(与单链表相同)
  2struct CircularNode {
  3    int data;
  4    struct CircularNode* next;
  5};
  6
  7// 创建新循环链表节点
  8struct CircularNode* createCircularNode(int data) {
  9    struct CircularNode* newNode = (struct CircularNode*)malloc(sizeof(struct CircularNode));
 10    newNode->data = data;
 11    newNode->next = newNode; // 初始化时指向自己
 12    return newNode;
 13}
 14
 15// 在循环链表头部插入节点
 16void insertAtHeadCircular(struct CircularNode** head, int data) {
 17    struct CircularNode* newNode = createCircularNode(data);
 18    if (*head == NULL) {
 19        *head = newNode;
 20    } else {
 21        struct CircularNode* temp = *head;
 22        while (temp->next != *head) {
 23            temp = temp->next;
 24        }
 25        temp->next = newNode;
 26        newNode->next = *head;
 27        *head = newNode;
 28    }
 29}
 30
 31// 在循环链表尾部插入节点
 32void insertAtTailCircular(struct CircularNode** head, int data) {
 33    struct CircularNode* newNode = createCircularNode(data);
 34    if (*head == NULL) {
 35        *head = newNode;
 36        return;
 37    }
 38
 39    struct CircularNode* temp = *head;
 40    while (temp->next != *head) {
 41        temp = temp->next;
 42    }
 43    temp->next = newNode;
 44    newNode->next = *head;
 45}
 46
 47// 在循环链表的指定位置插入节点
 48void insertAtPositionCircular(struct CircularNode** head, int data, int position) {
 49    if (position == 1) {
 50        insertAtHeadCircular(head, data);
 51        return;
 52    }
 53
 54    struct CircularNode* newNode = createCircularNode(data);
 55    struct CircularNode* temp = *head;
 56
 57    for (int i = 1; i < position - 1 && temp->next != *head; i++) {
 58        temp = temp->next;
 59    }
 60
 61    if (temp->next == *head) {
 62        printf("位置超出链表长度\n");
 63        return;
 64    }
 65
 66    newNode->next = temp->next;
 67    temp->next = newNode;
 68}
 69
 70// 删除循环链表头部节点
 71void deleteHeadCircular(struct CircularNode** head) {
 72    if (*head == NULL) return;
 73
 74    struct CircularNode* temp = *head;
 75    struct CircularNode* last = *head;
 76
 77    while (last->next != *head) {
 78        last = last->next;
 79    }
 80
 81    if (*head == last) {
 82        free(*head);
 83        *head = NULL;
 84    } else {
 85        last->next = (*head)->next;
 86        *head = (*head)->next;
 87        free(temp);
 88    }
 89}
 90
 91// 删除循环链表尾部节点
 92void deleteTailCircular(struct CircularNode** head) {
 93    if (*head == NULL) return;
 94
 95    struct CircularNode* temp = *head;
 96    struct CircularNode* prev = NULL;
 97
 98    while (temp->next != *head) {
 99        prev = temp;
100        temp = temp->next;
101    }
102
103    if (temp == *head) {
104        free(*head);
105        *head = NULL;
106    } else {
107        prev->next = *head;
108        free(temp);
109    }
110}
111
112// 删除循环链表的指定位置节点
113void deleteAtPositionCircular(struct CircularNode** head, int position) {
114    if (*head == NULL) return;
115
116    if (position == 1) {
117        deleteHeadCircular(head);
118        return;
119    }
120
121    struct CircularNode* temp = *head;
122    struct CircularNode* prev = NULL;
123
124    for (int i = 1; i < position && temp->next != *head; i++) {
125        prev = temp;
126        temp = temp->next;
127    }
128
129    if (temp->next == *head) {
130        printf("位置超出链表长度\n");
131        return;
132    }
133
134    prev->next = temp->next;
135    free(temp);
136}
137
138// 打印循环链表
139void printCircularList(struct CircularNode* head) {
140    if (head == NULL) return;
141    struct CircularNode* current = head;
142    do {
143        printf("%d -> ", current->data);
144        current = current->next;
145    } while (current != head);
146    printf("(head)\n");
147}

循环双链表

循环双链表不仅每个节点有前后指针,而且头节点和尾节点相连形成一个闭环。

  1// 循环双链表节点定义
  2struct CircularDoublyNode {
  3    int data;
  4    struct CircularDoublyNode* next;
  5    struct CircularDoublyNode* prev;
  6};
  7
  8// 创建新循环双链表节点
  9struct CircularDoublyNode* createCircularDoublyNode(int data) {
 10    struct CircularDoublyNode* newNode = (struct CircularDoublyNode*)malloc(sizeof(struct CircularDoublyNode));
 11    newNode->data = data;
 12    newNode->next = newNode;
 13    newNode->prev = newNode;
 14    return newNode;
 15}
 16
 17// 在循环双链表头部插入节点
 18void insertAtHeadCircularDoubly(struct CircularDoublyNode** head, int data) {
 19    struct CircularDoublyNode* newNode = createCircularDoublyNode(data);
 20    if (*head == NULL) {
 21        *head = newNode;
 22    } else {
 23        struct CircularDoublyNode* last = (*head)->prev;
 24        newNode->next = *head;
 25        newNode->prev = last;
 26        last->next = newNode;
 27        (*head)->prev = newNode;
 28        *head = newNode;
 29    }
 30}
 31
 32// 在循环双链表尾部插入节点
 33void insertAtTailCircularDoubly(struct CircularDoublyNode** head, int data) {
 34    struct CircularDoublyNode* newNode = createCircularDoublyNode(data);
 35    if (*head == NULL) {
 36        *head = newNode;
 37        return;
 38    }
 39
 40    struct CircularDoublyNode* last = (*head)->prev;
 41    newNode->next = *head;
 42    newNode->prev = last;
 43    last->next = newNode;
 44    (*head)->prev = newNode;
 45}
 46
 47// 在循环双链表的指定位置插入节点
 48void insertAtPositionCircularDoubly(struct CircularDoublyNode** head, int data, int position) {
 49    if (position == 1) {
 50        insertAtHeadCircularDoubly(head, data);
 51        return;
 52    }
 53
 54    struct CircularDoublyNode* newNode = createCircularDoublyNode(data);
 55    struct CircularDoublyNode* temp = *head;
 56
 57    for (int i = 1; i < position - 1 && temp->next != *head; i++) {
 58        temp = temp->next;
 59    }
 60
 61    if (temp->next == *head) {
 62        printf("位置超出链表长度\n");
 63        return;
 64    }
 65
 66    newNode->next = temp->next;
 67    newNode->prev = temp;
 68    temp->next->prev = newNode;
 69    temp->next = newNode;
 70}
 71
 72// 删除循环双链表头部节点
 73void deleteHeadCircularDoubly(struct CircularDoublyNode** head) {
 74    if (*head == NULL) return;
 75
 76    struct CircularDoublyNode* temp = *head;
 77    struct CircularDoublyNode* last = (*head)->prev;
 78
 79    if (*head == (*head)->next) {
 80        free(*head);
 81        *head = NULL;
 82    } else {
 83        last->next = (*head)->next;
 84        (*head)->next->prev = last;
 85        *head = (*head)->next;
 86        free(temp);
 87    }
 88}
 89
 90// 删除循环双链表尾部节点
 91void deleteTailCircularDoubly(struct CircularDoublyNode** head) {
 92    if (*head == NULL) return;
 93
 94    struct CircularDoublyNode* last = (*head)->prev;
 95    struct CircularDoublyNode* secondLast = last->prev;
 96
 97    if (last == *head) {
 98        free(*head);
 99        *head = NULL;
100    } else {
101        secondLast->next = *head;
102        (*head)->prev = secondLast;
103        free(last);
104    }
105}
106
107// 删除循环双链表的指定位置节点
108void deleteAtPositionCircularDoubly(struct CircularDoublyNode** head, int position) {
109    if (*head == NULL) return;
110
111    if (position == 1) {
112        deleteHeadCircularDoubly(head);
113        return;
114    }
115
116    struct CircularDoublyNode* temp = *head;
117    for (int i = 1; i < position && temp->next != *head; i++) {
118        temp = temp->next;
119    }
120
121    if (temp->next == *head) {
122        printf("位置超出链表长度\n");
123        return;
124    }
125
126    temp->prev->next = temp->next;
127    temp->next->prev = temp->prev;
128    free(temp);
129}
130
131// 打印循环双链表
132void printCircularDoublyList(struct CircularDoublyNode* head) {
133    if (head == NULL) return;
134    struct CircularDoublyNode* current = head;
135    do {
136        printf("%d <-> ", current->data);
137        current = current->next;
138    } while (current != head);
139    printf("(head)\n");
140}

最后修改于 2024-09-06 18:49