单链表的创建、插入、删除、查找
@Author: 张海拔
@Update: 2014-01-23
@Link: http://www.cnblogs.com/zhanghaiba/p/3530532.html
1 /* 2 *Author: ZhangHaiba 3 *Date: 2014-1-22 4 *File: single_linked_list.c 5 * 6 *single linked list demo 7 */ 8 9 #include <stdio.h> 10 #include <stdbool.h> 11 #include <stdlib.h> 12 #define INF 0x7fffffff 13 #define CMD_LNE 128 14 15 typedef struct node* link; 16 typedef struct node { 17 int item; 18 link next; 19 }node; 20 21 //public 22 link NODE(int item, link next); 23 link list_create(int n); 24 link list_reverse_create(int n); 25 bool list_insert(link head, int pos, int item); 26 bool list_delete(link head, int pos); 27 link list_search(link head, int item); 28 void list_travel(link head); 29 int list_length(link head); 30 void list_destroy(link head); 31 32 33 int main(void) 34 { 35 int n; 36 int pos, item; 37 char cmd[CMD_LNE]; 38 39 printf("Create list reversely enter '1', or naturally enter '0'.\n"); 40 int creation_mode; 41 scanf("%d", &creation_mode); 42 printf("Now we are gonna create list_a made by n nodes, please assign value of n:\n"); 43 scanf("%d", &n); 44 printf("Enter values of n items: \n"); 45 link list_a = creation_mode == 1 ? list_reverse_create(n) : list_create(n); 46 printf("The length of list_a is %d\n", list_length(list_a)); 47 printf("Now you can operate link_a by using command line.\n"); 48 bool flag = true; 49 while(flag) { 50 scanf("%s", cmd); 51 switch(cmd[0]) { 52 case 'i': 53 scanf("%d%d", &pos, &item); 54 if (list_insert(list_a, pos, item)) 55 printf("Inserted successfully!\n"); 56 else 57 printf("Insert failed! -- check pos\n"); 58 break; 59 case 'd': 60 scanf("%d", &item); 61 if (list_delete(list_a, item)) 62 printf("Delete successfully!\n"); 63 else 64 printf("Delete failed! -- check pos\n"); 65 break; 66 case 's': 67 scanf("%d", &item); 68 link ans = list_search(list_a, item); 69 ans == NULL ? printf("Not found!\n") : printf("Found item %d\n", ans->item); 70 break; 71 case 't': 72 list_travel(list_a); 73 break; 74 case 'q': 75 list_destroy(list_a); 76 printf("list_a have been destroy!\n"); 77 flag = false; 78 break; 79 default: 80 break; 81 } 82 } //while 83 return 0; 84 } 85 86 87 link NODE(int item, link next) 88 { 89 link born = malloc(sizeof (node)); 90 born->item = item; 91 born->next = next; 92 return born; 93 } 94 95 //create by 'tail insert' 96 link list_create(int n) 97 { 98 int i, item; 99 link head = NODE(INF, NULL); 100 link tail = head; 101 102 for (i = 0; i < n; ++i) { 103 scanf("%d", &item); 104 tail->next = NODE(item, NULL); 105 tail = tail->next; 106 } 107 return head; 108 } 109 110 //create by 'head insert' 111 link list_reverse_create(int n) 112 { 113 int i, item; 114 link head = NODE(INF, NULL), tmp; 115 116 for (i = 0; i < n; ++i) { 117 scanf("%d", &item); 118 tmp = head->next; 119 head->next = NODE(item, tmp); 120 } 121 return head; 122 } 123 124 int list_length(link head) 125 { 126 int cnt = 0; 127 128 for (head = head->next; head != NULL; head = head->next) 129 ++cnt; 130 return cnt; 131 } 132 133 bool list_insert(link head, int pos, int item) 134 { 135 //illegal position: insert nothing 136 if (pos < 0 || pos > list_length(head)) 137 return false; 138 while (pos--) 139 head = head->next; 140 link tmp = head->next; 141 head->next = NODE(item, tmp); 142 return true; 143 } 144 145 bool list_delete(link head, int pos) 146 { 147 //illegal position: delete nothing 148 if (pos < 0 || pos > list_length(head)-1) 149 return false; 150 while (pos--) 151 head = head->next; 152 link save = head->next; 153 head->next = save->next; 154 free(save); 155 return true; 156 } 157 158 link list_search(link head, int item) 159 { 160 for (head = head->next; head != NULL; head = head->next) 161 if (head->item == item) 162 return head; 163 return NULL; 164 } 165 166 void list_travel(link head) 167 { 168 for (head = head->next; head != NULL; head = head->next) 169 printf(head->next == NULL ? "%d\n" : "%d ", head->item); 170 } 171 172 void list_destroy(link head) 173 { 174 head->next == NULL ? free(head) : list_destroy(head->next); 175 }
测试示范:
ZhangHaiba-MacBook-Pro:code apple$ ./a.out Create list reversely enter '1', or naturally enter '0'. 1 Now we are gonna create list_a made by n nodes, please assign value of n: 6 Enter values of n items: 534 31 525 62 12 68 The length of list_a is 6 Now you can operate link_a by user command. t 68 12 62 525 31 534 i 0 44 Inserted successfully! t 44 68 12 62 525 31 534 i 8 99 Insert failed! -- check pos i 7 99 Inserted successfully! t 44 68 12 62 525 31 534 99 d -1 Delete failed! -- check pos d 0 Delete successfully! t 68 12 62 525 31 534 99 d 7 Delete failed! -- check pos d 6 Delete successfully! t 68 12 62 525 31 534 s 11 Not found! s 68 Found item 68 s 534 Found item 534 q list_a have been destroy!
对于带头节点的单链表的实现,值得注意的是,头插法和尾插法是相对创建方式而言,没有单独成为一个方法(函数)的必要。
而且这里提供了支持任意位置插入的函数list_insert()。
链式数据结构都是动态分配的空间,所有必须提供销毁函数(类似C++的析构函数)。这里的销毁函数联系到二叉树,可以看做是一叉树的后根(后序)遍历。
上述实现只有销毁函数是递归实现的,而其他函数都是迭代实现的,尽管递归实现也很自然,但考虑到用户空间栈有限,容易迭代实现的一律优先用迭代实现。
list_insert()和list_delete()函数返回bool类型是考虑到要对pos做边界检查。另外,C99的_Bool类型实在不怎么好看,而且没有定义true/false,所以还是用<stdbool>。
对于位置参数pos,其正确性应该由客户端或说API调用者负责。