链表(Linked List)的C语言实现
2017-08-20 23:40
417 查看
链表中的各对象按线性顺序排列,而其顺序是由各个对象里的指针所决定的。
链表有多种形式,它可以是单链接的或者双链接的,可以是已排序的或未排序的,可以是循环的或非循环的。
定义的结构体以及函数如下:
几个公共函数如下:
单链接的未排序非循环链表可以如如下实现:
各个函数的功能均可见其函数名与返回值。使用SLL时动态分配内存即可,如:
双链接的未排序非循环链表可如如下实现:
注意要点与单链接的未排序非循环链表相同。测试可如下:
单链接未排序的循环链表可如如下实现:
测试可如下:
有哨兵的双链接未排序循环链表可如如下实现:
测试可如下:
可以将其看为含有哨兵的一个循环的圆圈,这样理解比较方便。
链表有多种形式,它可以是单链接的或者双链接的,可以是已排序的或未排序的,可以是循环的或非循环的。
定义的结构体以及函数如下:
typedef struct SINGLE_LINKED_LIST { Node * head; Node * tail; } SLL; typedef struct CIRCULAR_SINGLE_LINKED_LIST { Node * head; Node * tail; } CSLL; typedef struct DOUBLE_LINKED_LIST { Node * head; Node * tail; } DLL; typedef struct CIRCULAR_DOUBLE_LINKED_LIST_WITH_SENTINEL { Node * nil; } CDLLS; void linked_list_traverse(Node * L); void linked_list_free(Node* L); Node* single_linked_list_insert(SLL * L, item_t item); Node* single_linked_list_search(SLL * L, item_t item); int single_linked_list_delete(SLL * L, Node * node); Node* circular_single_linked_list_insert(CSLL * L, item_t item); Node* circular_single_linked_list_search(CSLL * L, item_t item); int circular_single_linked_list_delete(CSLL * L, Node * node); Node* double_linked_list_insert(DLL * L, item_t item); Node* double_linked_list_search(DLL * L, item_t item); int double_linked_list_delete(DLL * L, Node * node); CDLLS* circular_double_linked_list_with_sentinel_init(); Node* circular_double_linked_list_with_sentinel_insert(CDLLS * L, item_t item); Node* circular_double_linked_list_with_sentinel_search(CDLLS * L, item_t item); int circular_double_linked_list_with_sentinel_delete(CDLLS * L, Node * node);
几个公共函数如下:
//functions for all kind of linked list void linked_list_traverse(Node* L) { if (L == NULL) { printf("Empty Linked List.\n"); } Node * pos = L; while (pos != NULL) { printf("%2d is in location:%9p. prev is %9p. next is %9p.\n", pos->item.key, \ pos, pos->prev, pos->next); pos = pos->next; if (pos == L) return; } } void linked_list_free(Node* L) { Node * pos = L; Node * f = L; while (pos != NULL && pos != L) { f = pos; pos = pos->next; free(f); } } //-----------------------------------------------------------------------
单链接的未排序非循环链表可以如如下实现:
//functions for single linked list Node* single_linked_list_insert(SLL * L, item_t item) { Node * node = (Node*)malloc(sizeof(Node)); node->item = item; node->prev = NULL; node->next = L->head; if (L->tail == NULL) L->tail = node; L->head = node; return node; } Node* single_linked_list_search(SLL * L, item_t item) { if (L->head == NULL) { fprintf(stderr, "The single linked list is empty.\n"); return NULL; } Node * pos = L->head; while (pos != NULL) { if (item.key == pos->item.key) return pos; pos = pos->next; } fprintf(stderr, "The item cannot be found.\n"); return NULL; } int single_linked_list_delete(SLL * L, Node * node) { if (L->head == NULL) { fprintf(stderr, "The single linked list is empty.\n"); return 0; } if (node == NULL) { fprintf(stderr, "The node is NULL.\n"); return 0; } if (L->head == node) { L->head = node->next; if (L->head == NULL) L->tail = NULL; return 1; } Node * pos = L->head; while (pos != NULL && pos->next != node) { pos = pos->next; } if (pos->next = node) { if (node == L->tail) L->tail = pos; pos->next = pos->next->next; return 1; } fprintf(stderr, "No such node in linked list.\n"); return 0; } int single_linked_list_reverse(SLL * L) { if (L->head == NULL) { fprintf(stderr, "The single linked list is empty.\n"); return 0; } L->tail = L->head; Node *pre, *current, *next; pre = L->head; current = L->head->next; L->head->next = NULL; next = NULL; while (current != NULL) { next = current->next; current->next = pre; pre = current; current = next; } L->head = pre; return 1; } //------------------------------------------------------------------------
各个函数的功能均可见其函数名与返回值。使用SLL时动态分配内存即可,如:
void test_for_single_linked_list() { SLL * L = (SLL*)malloc(sizeof(SLL)); printf("%p\n", L->head); item_t item = {10, NULL}; Node * node; for (int i = 0; i < 10; i++) { item.key = i + 10; single_linked_list_insert(L, item); } printf("SLL head is in location:%p\n", L->head); linked_list_traverse(L->head); single_linked_list_reverse(L); linked_list_traverse(L->head); for (int i = -1; i <= 10; i++) { item.key = i + 10; node = single_linked_list_search(L, item); if (node != NULL) printf("Node %d in location %p delete :%d\n", node->item.key, node, \ single_linked_list_delete(L, node)); //printf("SLL tail is in location:%p\n", L->tail); } printf("---------------------------------------------\n"); for (int i = 0; i < 10; i++) { item.key = i + 10; single_linked_list_insert(L, item); } printf("SLL head is in location:%p\n", L->head); linked_list_traverse(L->head); for (int i = 11; i >= -1; i--) { item.key = i + 10; node = single_linked_list_search(L, item); if (node != NULL) printf("Node %d in location %p delete :%d\n", node->item.key, node, \ single_linked_list_delete(L, node)); //printf("SLL tail is in location:%p\n", L->tail); } linked_list_free(L->head); free(L); }
双链接的未排序非循环链表可如如下实现:
//functions for double linked list Node* double_linked_list_insert(DLL * L, item_t item) { Node * node = (Node*)malloc(sizeof(Node)); node->prev = NULL; node->item = item; node->next = L->head; if (L->head != NULL) L->head->prev = node; else L->tail = node; L->head = node; return node; } Node* double_linked_list_search(DLL * L, item_t item) { if (L->head == NULL) { fprintf(stderr, "The double linked list is empty.\n"); return NULL; } Node * pos = L->head; while (pos != NULL) { if (pos->item.key == item.key) return pos; pos = pos->next; } fprintf(stderr, "The item cannot be found.\n"); return NULL; } int double_linked_list_delete(DLL * L, Node * node) { if (L->head == NULL) { fprintf(stderr, "The double linked list is empty.\n"); return 0; } if (node == NULL) { fprintf(stderr, "The node is NULL.\n"); return 0; } if (node == L->tail) L->tail = node->prev; if (node->prev != NULL) { node->prev->next = node->next; } else { L->head = node->next; } if (node->next != NULL) { node->next->prev = node->prev; } return 1; } //----------------------------------------------------------------------------
注意要点与单链接的未排序非循环链表相同。测试可如下:
void test_for_double_linked_list() { DLL * L = (DLL*)malloc(sizeof(DLL)); printf("%p\n", L->head); item_t item = {10, NULL}; Node * node; for (int i = 0; i < 10; i++) { item.key = i + 10; double_linked_list_insert(L, item); } printf("DLL head is in location:%p\n", L->head); linked_list_traverse(L->head); for (int i = -1; i <= 10; i++) { item.key = i + 10; node = double_linked_list_search(L, item); if (node != NULL) printf("Node %d in location %p delete :%d\n", node->item.key, node, \ double_linked_list_delete(L, node)); //printf("DLL tail is in location:%p\n", L->tail); } printf("---------------------------------------------\n"); for (int i = 0; i < 10; i++) { item.key = i + 10; double_linked_list_insert(L, item); } printf("DLL head is in location:%p\n", L->head); linked_list_traverse(L->head); for (int i = 11; i >= -1; i--) { item.key = i + 10; node = double_linked_list_search(L, item); if (node != NULL) printf("Node %d in location %p delete :%d\n", node->item.key, node, \ double_linked_list_delete(L, node)); //printf("DLL tail is in location:%p\n", L->tail); } linked_list_free(L->head); free(L); }
单链接未排序的循环链表可如如下实现:
//functinos for circular single linked list Node* circular_single_linked_list_insert(CSLL * L, item_t item) { Node * node = (Node*)malloc(sizeof(Node)); node->item = item; node->prev = NULL; if (L->head == NULL) { L->head = node; L->tail = node; node->next = node; } else { node->next = L->head; L->head = node; L->tail->next = node; } return node; } Node* circular_single_linked_list_search(CSLL * L, item_t item) { if (L->head == NULL) { fprintf(stderr, "The circular single linked list is empty.\n"); return NULL; } Node * pos = L->head; if (pos->item.key == item.key) return pos; else pos = pos->next; while (pos->item.key != item.key && pos != L->head) { pos = pos->next; } if (pos != L->head) return pos; fprintf(stderr, "The item cannot be found.\n"); return NULL; } int circular_single_linked_list_delete(CSLL * L, Node * node) { if (L->head == NULL) { fprintf(stderr, "The circular single linked list is empty.\n"); return 0; } if (node == NULL) { fprintf(stderr, "The node is NULL.\n"); return 0; } if (node == L->head && node == L->tail) { L->head = NULL; L->tail = NULL; return 1; } else if (node == L->head) { L->head = node->next; L->tail->next = L->head; return 1; } Node * pos = L->head; while (pos->next != node && pos != L->tail) { pos = pos->next; } if (pos->next == node) { if (node == L->tail) { L->tail = pos; } pos->next = node->next; return 1; } fprintf(stderr, "No such node in linked list.\n"); return 0; } //------------------------------------------------------------------------
测试可如下:
void test_for_circular_single_linked_list() { CSLL * L = (CSLL*)malloc(sizeof(CSLL)); printf("%p\n", L->head); item_t item = {10, NULL}; Node * node; for (int i = 0; i < 10; i++) { item.key = i + 10; circular_single_linked_list_insert(L, item); } printf("CSLL head is in location:%p\n", L->head); linked_list_traverse(L->head); for (int i = -1; i <= 10; i++) { item.key = i + 10; node = circular_single_linked_list_search(L, item); if (node != NULL) printf("Node %d in location %p delete :%d\n", node->item.key, node, \ circular_single_linked_list_delete(L, node)); //linked_list_traverse(L->head); } printf("---------------------------------------------\n"); for (int i = 0; i < 10; i++) { item.key = i + 10; circular_single_linked_list_insert(L, item); } printf("CSLL head is in location:%p\n", L->head); linked_list_traverse(L->head); for (int i = 11; i >= -1; i--) { item.key = i + 10; node = circular_single_linked_list_search(L, item); if (node != NULL) printf("Node %d in location %p delete :%d\n", node->item.key, node, \ circular_single_linked_list_delete(L, node)); } linked_list_free(L->head); free(L); }
有哨兵的双链接未排序循环链表可如如下实现:
//functions for cicular double linked list with sentinel CDLLS* circular_double_linked_list_with_sentinel_init() { CDLLS * L = (CDLLS*)malloc(sizeof(CDLLS)); L->nil = (Node*)malloc(sizeof(Node)); L->nil->next = L->nil; L->nil->prev = L->nil; return L; } Node* circular_double_linked_list_with_sentinel_insert(CDLLS * L, item_t item) { Node * node = (Node*)malloc(sizeof(Node)); node->item = item; node->next = L->nil->next; L->nil->next->prev = node; node->prev = L->nil; L->nil->next = node; return node; } Node* circular_double_linked_list_with_sentinel_search(CDLLS * L, item_t item) { if (L->nil->next == L->nil) { fprintf(stderr, "The circular double linked list is empty.\n"); return NULL; } Node* pos = L->nil->next; while (pos != L->nil && pos->item.key != item.key) { pos = pos->next; } if (pos == L->nil) { fprintf(stderr, "The item cannot be found.\n"); return NULL; } else { return pos; } } int circular_double_linked_list_with_sentinel_delete(CDLLS * L, Node * node) { if (L->nil->next == L->nil) { fprintf(stderr, "The circular double linked list is empty.\n"); return 0; } if (node == NULL) { fprintf(stderr, "The node is NULL.\n"); return 0; } node->prev->next = node->next; node->next->prev = node->prev; return 1; } //--------------------------------------------------------------------------
测试可如下:
void test_for_circular_double_linked_list() { CDLLS * L = circular_double_linked_list_with_sentinel_init(); printf("%p %p %p %p\n", L, L->nil, L->nil->prev, L->nil->prev); item_t item = {10, NULL}; Node * node; for (int i = 0; i < 10; i++) { item.key = i + 10; circular_double_linked_list_with_sentinel_insert(L, item); } printf("CDLLS nil is in location:%p\n", L->nil); linked_list_traverse(L->nil); for (int i = -1; i <= 10; i++) { item.key = i + 10; node = circular_double_linked_list_with_sentinel_search(L, item); if (node != NULL) printf("Node %d in location %p delete :%d\n", node->item.key, node, \ circular_double_linked_list_with_sentinel_delete(L, node)); } printf("---------------------------------------------\n"); for (int i = 0; i < 10; i++) { item.key = i + 10; circular_double_linked_list_with_sentinel_insert(L, item); } printf("CDLLS nil is in location:%p\n", L->nil); linked_list_traverse(L->nil); for (int i = 11; i >= -1; i--) { item.key = i + 10; node = circular_double_linked_list_with_sentinel_search(L, item); if (node != NULL) printf("Node %d in location %p delete :%d\n", node->item.key, node, \ circular_double_linked_list_with_sentinel_delete(L, node)); } linked_list_free(L->nil); free(L); }
可以将其看为含有哨兵的一个循环的圆圈,这样理解比较方便。
相关文章推荐
- [leetcode]Reverse Linked List II (反转链表值 C语言实现)
- list.c - A linked list by C --- C语言实现的单向链表
- list.c - A linked list by C --- C语言实现的单向链表
- C语言实现单链表(LinkedList)
- C语言实现双向链表(DoublyLinkedList)
- C语言实现一个简单的单向链表list
- 根据链表的原理,自己实现一个简易版的LinkedList
- 【LeetCode-面试算法经典-Java实现】【142-Linked List Cycle II(单链表中有环II)】
- 【数据结构】链表LinkedList分析与关键实现
- 双向链表的C++实现 Implement of Doubly Linked List
- C实现 LeetCode->Linked List Cycle 双指针大法)(单链表是否有环)
- 【LeetCode-面试算法经典-Java实现】【092-Reverse Linked List II(反转单链表II)】
- 基于jdk的list 和 队列 linkedList 和父亲长子兄弟链表模型 实现的 树 的前序遍历,后序遍历和层次遍历
- LinkedList : 双向链表与实现
- 黑马程序员————LinkedList和c语言中的链表
- 链表线性表的c语言实现方式 seqlist.h 和 seqlist.c
- 自行实现LinkedList (链表) --Java版
- 链表(LinkedList) C 语言实现
- 49. 3种方法实现复杂链表的复制[clone of complex linked list]
- LinkedList,双向链表的实现