码迷,mamicode.com
首页 > 编程语言 > 详细

[算法天天练] - C语言实现双向链表(一)

时间:2015-04-03 15:06:57      阅读:193      评论:0      收藏:0      [点我收藏+]

标签:

双向链表是比较常见的,主要是在链表的基础上添加prev指针,闲话少说直接上代码吧(这个也是网上一个大神的思路,真心不错,条理清楚,逻辑缜密)

主要也是为了学习,贴上我所调试成功的代码(Linux环境下)

双向链表代码:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 
  4 typedef struct NodeTag Node;
  5 typedef struct LinkedListTag LinkedList;
  6 
  7 struct NodeTag
  8 {
  9  Node* prev;
 10  Node* next;
 11  void* data;
 12 };
 13 
 14 struct LinkedListTag
 15 {
 16  Node* head;
 17  Node* tail;
 18  Node* cur;
 19  int size;
 20 };
 21 
 22 // 创建一个链表 成功返回该链表的指针 否则返回NULL
 23 LinkedList* Create( void )
 24 {
 25  // 创建一个新节点
 26  LinkedList* list = (LinkedList*)malloc(sizeof(LinkedList));
 27  // 创建不成功,返回NULL
 28  if(!list) return NULL;
 29  
 30  list->head = NULL;
 31  list->tail = NULL;
 32  list->cur  = NULL;
 33  list->size = 0;
 34  
 35  // 初始化成功后,返回list
 36  return list;
 37 }
 38 
 39 // 将元素添加到链表的末尾,成功返回链表的size,失败返回-1
 40 int AddBack(LinkedList* list, void* data)
 41 {
 42  // 创建一个新节点,创建不成功的话,返回-1
 43  Node* node = (Node *)malloc(sizeof(Node));
 44  if(!node) return -1;
 45  
 46  // 为节点的数据域赋值
 47  node->data = data;
 48  // 如果为链表的末尾
 49  if(list->tail)
 50  {
 51   list->tail->next = node;         // 把新节点赋给链表末尾的下一个
 52   node->prev       = list->tail;   // 新节点的前一个等于之前的末节点
 53   node->next       = NULL;         // 新节点为末节点,把它下一个指向NULL
 54  }
 55  else // 如果不为末尾,其实就是空链表
 56  {
 57   node->next       = NULL;         // 新节点的下一个为NULL
 58   node->prev       = NULL;         // 新节点的前一个为NULL
 59   list->head       = node;         // 链表的头为新节点node
 60  }
 61  list->tail = node;                   // 链表的末尾指向node
 62  
 63  return ++list->size;                 // 返回链表的size
 64 }
 65 
 66 // 将元素添加到链表前端,成功返回非0,否则返回0
 67 int AddFront(LinkedList* list, void* data)
 68 {
 69  Node *node = (Node*)malloc(sizeof(Node));
 70  if(!node) return 0;
 71  
 72  node->data = data;
 73  if(list->head)
 74  {
 75   list->head->prev = node;
 76   node->next       = list->head;
 77   node->prev       = NULL;
 78  }
 79  else
 80  {
 81   node->next       = NULL;
 82   node->prev       = NULL;
 83   list->tail       = node;
 84  }
 85  list->head = node;
 86  
 87  return ++list->size;
 88 }
 89 
 90 // 将元素从末端移除并返回该元素,如果链表为空则返回NULL
 91 void* RemoveBack(LinkedList* list)
 92 {
 93  Node* temp;
 94  void* data;
 95  
 96  if(!list->size) return NULL;
 97  
 98  temp = list->tail;
 99  data = list->tail->data;
100  
101  if(list->head == list->tail)
102  {
103   list->head = NULL;
104   list->tail = NULL;
105   list->cur  = NULL;
106  }
107  else
108  {
109   list->tail = list->tail->prev;
110   list->tail->next = NULL;
111  }
112  --list->size;
113  free(temp);
114  return data;
115 }
116 
117 // 将元素从前端移除并返回该元素,如果链表为空则返回NULL
118 void* RemoveFront(LinkedList* list)
119 {
120  Node* temp;
121  void* data;
122  
123  if(!list->size) return NULL;
124  
125  temp = list->head;
126  data = list->head->data;
127  
128  if(list->head == list->tail)
129  {
130   list->head = NULL;
131   list->tail = NULL;
132   list->cur  = NULL;
133  }
134  else
135  {
136   list->head = list->head->next;
137   list->head->prev = NULL;
138  }
139  --list->size;
140  free(temp);
141  return data;
142 }
143 
144 /* 如果当前链表为空则返回非0,否则返回0 */
145 int IsEmpty(LinkedList* list)
146 {
147     return list->size == 0;
148 }
149 
150 /* 获得链表的大小(元素总个数) */
151 int Size(LinkedList* list)
152 {
153     return list->size;
154 }
155 
156 /* 将当前位置移动到链表的开始 */
157 void Begin(LinkedList* list)
158 {
159     list->cur = list->head;
160 }
161 
162 /* 将当前位置移动到链表的最后 */
163 void End(LinkedList* list)
164 {
165     list->cur = list->tail;
166 }
167 /* 将当前位置向后移动一个位置 */
168 void MoveNext(LinkedList* list)
169 {
170     list->cur = list->cur->next;
171 }
172 
173 /* 将当前位置向后移动一个位置 */
174 void MovePrev(LinkedList* list)
175 {
176     list->cur = list->cur->prev;
177 }
178 
179 /* 清空链表中所有元素 */
180 void Clear(LinkedList* list)
181 {
182  while(RemoveBack(list));
183 }
184 
185 /* 销毁一个链表 */
186 void Destroy(LinkedList* list)
187 {
188  Clear(list);
189  free(list);
190 }
191 
192 /* 如果当前位置之后还有元素则返回非0,否则返回0 */
193 int HasNext(LinkedList* list)
194 {
195     if (!list->cur) return 0;
196     if (list->cur == list->tail) return 1;
197     return list->cur->next != NULL;
198 }
199 
200 /* 如果当前位置之前还有元素则返回非0,否则返回0 */
201 int HasPrev(LinkedList* list)
202 {
203     if (!list->cur) return 0;
204     if (list->cur == list->head) return 1;
205     return list->cur->prev != NULL;
206 }
207 
208 /* 返回当前位置的元素 */
209 void* Current(LinkedList* list)
210 {
211     return list->cur->data;
212 }
213 
214  
215 
216 // 正向打印链表
217 void Traverse(LinkedList* list)
218 {
219  for( Begin(list); HasNext(list); MoveNext(list) )
220   printf("%d ", *(int*)Current(list));
221  putchar(\n);
222 }
223 
224 // 反向打印链表
225 void RTraverse(LinkedList* list)
226 {
227     for (End(list); HasPrev(list); MovePrev(list))
228         printf("%d ", *(int*)Current(list));
229     putchar(\n);
230 }
231 
232 
233 int main()
234 {
235  int i;
236  LinkedList* list = Create();
237  
238  int array1[10];
239  int array2[10];
240  
241  for(i=0; i<10; i++)
242  {
243   array1[i] = i+1;
244   array2[i] = i+100+1;
245   AddBack(list, &array1[i]); 
246  }
247  
248  printf("链表大小(SIZE): %d\n", Size(list));
249  
250  printf("正向打印链表:\n");
251  Traverse(list);
252  printf("反向打印链表:\n");
253  RTraverse(list);
254  
255  printf("添加array2[0]数\n");
256  AddBack(list, &array2[0]);
257  
258  printf("链表大小(SIZE): %d\n", Size(list));
259  printf("正向打印链表:\n");
260  Traverse(list);
261  printf("反向打印链表:\n");
262  RTraverse(list);
263  
264  printf("调用AddFront函数,添加array2[0]数\n");
265  AddFront(list, &array2[1]);
266  
267  printf("链表大小(SIZE): %d\n", Size(list));
268  printf("正向打印链表:\n");
269  Traverse(list);
270  printf("反向打印链表:\n");
271  RTraverse(list);
272  
273  printf("从末尾移除的元素是: %d\n", *(int *)RemoveBack(list));
274  printf("链表大小(SIZE): %d\n", Size(list));
275  printf("正向打印链表:\n");
276  Traverse(list);
277  printf("反向打印链表:\n");
278  RTraverse(list);
279  
280  printf("从开头移除的元素是: %d\n", *(int *)RemoveFront(list));
281  printf("链表大小(SIZE): %d\n", Size(list));
282  printf("正向打印链表:\n");
283  Traverse(list);
284  printf("反向打印链表:\n");
285  RTraverse(list);
286  
287  printf("清空链表,Clear(list)后\n");
288  Clear(list);
289  printf("链表大小(SIZE): %d\n", Size(list));
290  
291  for(i=0; i<10; i++)
292  {
293   AddFront(list, &array2[i]);
294  }
295  printf("正向打印链表:\n");
296  Traverse(list);
297  printf("反向打印链表:\n");
298  RTraverse(list);
299  
300  Destroy(list);
301  printf("销毁链表Destroy(list)\n");
302  
303  return 0;
304 }

 

以下是执行结果:

链表大小(SIZE): 10
正向打印链表:
1 2 3 4 5 6 7 8 9 10 
反向打印链表:
10 9 8 7 6 5 4 3 2 1 
添加array2[0]数
链表大小(SIZE): 11
正向打印链表:
1 2 3 4 5 6 7 8 9 10 101 
反向打印链表:
101 10 9 8 7 6 5 4 3 2 1 
调用AddFront函数,添加array2[0]数
链表大小(SIZE): 12
正向打印链表:
102 1 2 3 4 5 6 7 8 9 10 101 
反向打印链表:
101 10 9 8 7 6 5 4 3 2 1 102 
从末尾移除的元素是: 101
链表大小(SIZE): 11
正向打印链表:
102 1 2 3 4 5 6 7 8 9 10 
反向打印链表:
10 9 8 7 6 5 4 3 2 1 102 
从开头移除的元素是: 102
链表大小(SIZE): 10
正向打印链表:
1 2 3 4 5 6 7 8 9 10 
反向打印链表:
10 9 8 7 6 5 4 3 2 1 
清空链表,Clear(list)后
链表大小(SIZE): 0
正向打印链表:
110 109 108 107 106 105 104 103 102 101 
反向打印链表:
101 102 103 104 105 106 107 108 109 110 
销毁链表Destroy(list)

 

在世界上,努力坚持的绝对不是自己一个人,好好努力会成功的。

[算法天天练] - C语言实现双向链表(一)

标签:

原文地址:http://www.cnblogs.com/eternal1025/p/4389866.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!