常用链表操作总结

--常用链表操作总结--(转)

1. 求单链表中结点的个数
2. 将单链表反转
3. 查找单链表中的倒数第K个结点(k > 0)
4. 查找单链表的中间结点
5. 从尾到头打印单链表
6. 已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序
7. 判断一个单链表中是否有环
8. 判断两个单链表是否相交
9. 求两个单链表相交的第一个节点
10. 已知一个单链表中存在环,求进入环中的第一个节点
11. 给出一单链表头指针pHead和一节点指针pToBeDeleted,O(1)时间复杂度删除节点pToBeDeleted

 

  1 /****************************************
  2 * File Name: l1.cpp
  3 * Author: sky0917
  4 * Created Time: 2014年01月11日 21:50:22
  5 ****************************************/
  6 #include <map>
  7 #include <cmath>
  8 #include <queue>
  9 #include <stack>
 10 #include <cstdio>
 11 #include <cstring>
 12 #include <algorithm>
 13 using namespace std;
 14 
 15 struct Node{
 16     int key;
 17     Node *next;
 18     Node(){
 19         key = 0;
 20         next = NULL;
 21     }
 22 };
 23 
 24 // 1. 求单链表中节点的个数 
 25 int getListLength(Node *head){     
 26 
 27     if (head->next == NULL) 
 28         return 0;
 29     int ListLength = 0;
 30     Node *p = head->next;
 31     while (p != NULL){
 32         ListLength++;
 33         p = p->next;
 34     }
 35 
 36     return ListLength;
 37 }
 38 
 39 // 2. 将单链表反转
 40 void reverseList(Node *head){
 41 
 42     if (head->next == NULL)
 43         return;    
 44 
 45     Node *p1, *p2, *p3;
 46 
 47     p2 = head->next;
 48     if (p2->next == NULL)//只有一个元素,直接返回
 49         return;    
 50     
 51     p1 = p2->next;
 52     p2->next = NULL;
 53 
 54     while (p1 != NULL){
 55         p3 = p1->next;
 56         p1->next = p2;
 57         p2 = p1;
 58         p1 = p3;
 59     }    
 60     head->next = p2;
 61 }
 62 
 63 // 3. 查找单链表中的倒数第K个结点(k > 0)
 64 int GetRkthNode(Node *head, int k){
 65 
 66     Node *pf = head;
 67     if (NULL == pf->next)
 68         return -1;
 69     if (k <= 0)
 70         return -1;
 71 
 72     int tot = 0;
 73     while (pf->next != NULL){
 74         tot++;
 75         pf = pf->next;    
 76         if (tot == k) break;
 77     }
 78     if (tot < k) return -1;
 79     
 80     Node *pr = head->next;
 81     while (pf->next != NULL){
 82         pf = pf->next;
 83         pr = pr->next;    
 84     }    
 85     return pr->key;
 86 }
 87 
 88 // 4. 查找单链表的中间结点
 89 Node* getMidNode(Node *head){
 90 
 91     Node *pf = head->next;
 92     if (pf == NULL)
 93         return head;
 94 
 95     if (pf->next == NULL)
 96         return pf;
 97 
 98     Node *pr = head->next;
 99     while (pf->next != NULL){
100         pf = pf->next;
101         pr = pr->next;    
102         if (pf->next != NULL){
103             pf = pf->next;
104         }
105     }
106     return pr;
107 }
108 
109 // 5. 从尾到头打印单链表
110 void rPrintList(Node *head){
111 
112     stack<Node *> s;
113     Node *p = head;
114     
115     if (p->next == NULL)
116         return;
117     
118     while (p->next != NULL){
119         s.push(p->next);
120         p = p->next;    
121     }
122     
123     while (!s.empty()){
124         p = s.top();
125         printf("%d->",p->key);
126         s.pop();
127     }
128     puts("");
129 }
130 
131 // 5. 从尾到头打印单链表(2)
132 void dfsPrint(Node *p){
133 
134     if (p == NULL)
135         return;
136     
137     dfsPrint(p->next);
138     printf("%d->",p->key);
139 
140 }
141 void rPrintList2(Node *head){
142 
143     Node *p = head;
144 
145     if (p->next == NULL)
146         return;
147      
148     dfsPrint(p->next);
149     puts("");
150 }
151 
152 // 6. 已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序
153 Node *mergeSortedList(Node *head, Node *head2){
154 
155     Node *p1 = head->next;
156     Node *p2 = head2->next;
157 
158     if (p1 == NULL)
159         return head2;
160     if (p2 == NULL)
161         return head;
162         
163     Node *mHead = NULL;
164     if (p1->key < p2->key){
165         mHead = head;
166         mHead->next = NULL;
167     }
168     else{
169         mHead = head2;
170         mHead->next = NULL;
171     }    
172 
173     Node *pm = mHead;
174     while (p1 != NULL && p2 != NULL){
175         if (p1->key < p2->key){
176             pm->next = p1;
177             p1 = p1->next;
178             pm = pm->next;
179             pm->next = NULL;            
180         }
181         else{
182             pm->next = p2;
183             p2 = p2->next;
184             pm = pm->next;
185             pm->next == NULL;
186         }
187     }
188 
189     while (p1 != NULL){
190         pm->next = p1;
191         p1 = p1->next;
192         pm = pm->next;
193         pm->next = NULL;
194     }
195     while (p2 != NULL){
196         pm->next = p2;
197         p2 = p2->next;
198         pm = pm->next;
199         pm->next = NULL;
200     }
201     return mHead;
202 }
203 
204 // 7. 判断一个单链表中是否有环
205 bool hasCircle(Node *head){
206 
207     if (head == NULL) 
208         return false;
209 
210     Node *pFast = head->next;
211     Node *pSlow = head->next;
212     
213     while (pFast != NULL && pFast->next != NULL){
214         pFast = pFast->next->next;
215         pSlow = pSlow->next;
216         if (pSlow == pFast)
217             return true;
218     }
219     return false;
220 }
221 
222 // 8. 判断两个单链表是否相交
223 bool isIntersect(Node *head1, Node *head2){
224     
225     if (head1 == NULL || head2 == NULL)
226         return false;
227 
228     Node *p1 = head1;
229     while (p1->next != NULL){
230         p1 = p1->next;
231     }    
232 
233     Node *p2 = head2;
234     while (p2->next != NULL){
235         p2 = p2->next;
236     }
237     
238     return p1 == p2;
239 }
240       
241 // 9. 求两个单链表相交的第一个节点
242 Node *getFirstCommonNode(Node *head1, Node *head2){
243     
244     if (head1 == NULL || head2 == NULL)
245         return NULL;
246 
247     int len1 = 0;
248     Node *p1 = head1;
249     while (p1->next != NULL){
250         p1 = p1->next;
251         len1++;
252     }
253 
254     int len2 = 0;
255     Node *p2 = head2;
256     while (p2->next != NULL){
257         p2 = p2->next;
258         len2++;
259     }
260      
261     if (p1 != p2) 
262         return NULL;
263     
264     p1 = head1;
265     p2 = head2;
266     
267     if (len1 > len2){
268         int k = len1 - len2;
269         while (k--){
270             p1 = p1->next;
271         }
272     }
273     else{
274         int k = len2 - len1;
275         while (k--){
276             p2 = p2->next;
277         }
278     }
279     while (p1 != p2){
280         p1 = p1->next;
281         p2 = p2->next;
282     }
283     return p1;
284 }
285 
286 // 10. 已知一个单链表中存在环,求进入环中的第一个节点
287 Node *getFirstNodeInCircle(Node *head){
288     
289     if (head == NULL || head->next == NULL)
290         return NULL;
291      
292     Node *pFast = head;
293     Node *pSlow = head;
294     while (pFast != NULL && pFast->next != NULL){
295         pFast = pFast->next->next;
296         pSlow = pSlow->next;
297         if (pFast == pSlow)
298             break;
299     }
300     if (pFast == NULL || pFast->next == NULL)
301         return NULL;
302     
303     Node *ptmp = pSlow;
304     Node *ph1 = head->next;
305     Node *ph2 = ptmp->next;
306     
307     int len1 = 0;
308     Node *p1 = ph1;
309     while (p1 != ptmp){
310         p1 = p1->next;
311         len1++;
312     }
313     
314     int len2 = 0;
315     Node *p2 = ph2;
316     while (p2 != ptmp){
317         p2 = p2->next;
318         len2++;
319     }    
320 
321     p1 = ph1;
322     p2 = ph2;
323     
324     if (len1 > len2){
325         int k = len1 - len2;
326         while (k--){
327             p1 = p1->next;
328         }
329     }
330     else{
331         int k = len2 - len1;
332         while (k--){
333             p2 = p2->next;
334         }
335     }
336     while (p1 != p2){
337         p1 = p1->next;
338         p2 = p2->next;    
339     }
340     return p1;
341 }
342 
343 // 11. 给出一单链表头指针pHead和一节点指针pToBeDeleted,O(1)时间复杂度删除节点pToBeDeleted
344 void deleteNode(Node *head, Node *pd){
345     
346     if (head == NULL || pd == NULL)
347         return;
348     
349     if (pd->next != NULL){
350         pd->key = pd->next->key;
351         Node *ptmp = pd->next;
352         pd->next = pd->next->next;
353         delete ptmp;
354     }
355     else{
356         Node *p = head;
357         while (p->next != pd){
358             p = p->next;
359         }
360         p->next = NULL;
361         delete pd;    
362     }
363 }
364 
365 int main(){
366 
367     void init(Node *head); 
368     void print(Node *head);
369     Node *head = new Node();
370 
371     init(head);    
372     print(head);
373 
374     /*
375      * @求单链表中节点的个数
376      */
377     int len = getListLength(head); 
378     printf("len = %d\n",len);    
379 
380     /* 
381      * @将单链表反转
382      */
383     reverseList(head); 
384     print(head);
385 
386     /* 
387      * @将单链表反转
388      */
389     reverseList(head);  
390     print(head); 
391 
392     /*
393      *@ 返回链表的倒数第 k 个元素的值
394      *  用两个指针,让第一个指针先走k个元素,然后第二个指针和第一个指针一起走,
395      *  但第一个指针走到尾部的时候,第二个就走到了倒数第k个元素的位置
396      */
397     int kth = GetRkthNode(head, 5);
398     printf("kth = %d\n",kth);
399 
400     /*
401      * @查找单链表的中间结点
402      * 设置两个指针,两个指针同时向前走,前面的指针每次走两步,后面的指针每次走一步,
403      * 前面的指针走到最后一个结点时,后面的指针所指结点就是中间结点,即第(n/2+1)个
404      * 结点
405      * 时间复杂度 O(n)
406      */ 
407     Node *midNode = getMidNode(head);    
408     printf("midNode.val = %d\n",midNode->key);
409 
410     /*
411      * @从尾到头打印单链表
412      *  两种方式:一个是自己模拟栈,另一种是调用系统栈
413      *  时间复杂度 O(n)
414      */
415     rPrintList(head);        
416     rPrintList2(head);
417 
418     /*
419      *@已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序
420      * 类似归并排序。
421      * 注意两个链表都为空,和其中一个为空时的情况。
422      * O(1)的空间,时间复杂度为O(max(len1, len2))。
423      */
424     Node *head2 = new Node();
425     init(head2);
426     Node *mhead = mergeSortedList(head, head2);
427     print(mhead);    
428 
429     /*
430      * @判断一个单链表中是否有环
431      * 用两个指针,一个指针一次走两步,一个指针一次走一步,如果有环,两个指针肯定会在环中相遇。
432      * 时间复杂度为O(n)
433      */
434 //    mhead->next->next->next = mhead->next;
435     if (hasCircle(mhead))
436         printf("有环\n");
437     else printf("无环\n");    
438     
439     /*
440      * @判断两个单链表是否相交鱼某一点
441      *  如果两个链表相交鱼某一点,那么在这个相交节点之后的所有节点都是两个链表所共有的。
442      *  所以如果相交那么最后一个节点一定是共有的。
443      *  可以先遍历第一个链表记住最后一个节点,然后遍历第二个链表,到最后一个节点时和第一
444      *  个链表的最后一个节点比较,如果相同,则相交,否则不相交。
445      *  时间复杂度O(len1+len2) 空间复杂度为O(1)
446      */    
447      
448      if (isIntersect(head, mhead))
449          printf("相交\n");
450      else printf("不相交\n");
451     
452      /*
453       * @求两个单链表相交的第一个节点
454       * 先遍历第一个单链表,计算其长度len1, 同时保存最后一个节点的地址
455       * 再遍历第二个单链表,计算其长度len2, 同时查看最后一个节点是否和第一个链表的最后
456       * 一个节点相同,如果不相同,说明不想交,直接返回。
457       * 再次从头遍历两个链表,如果len1 > len2,那么第一个链表先遍历Len1-len2个节点,这个
458       * 时候两个链表当前节点距离第一个相交节点的距离相同,只要一起遍历,直到两个节点的
459       * 地址相同即可。
460       * 时间复杂度O(len1+len2)
461       */
462       Node *pt = getFirstCommonNode(head, mhead);
463       if (pt != NULL)
464           printf("FirstCommonNode's value is %d\n",pt->key);
465       else printf("No intersect\n"); 
466 
467      /*
468       * @已知一个单链表有环,求进入环中的第一个节点
469       *  首先判断是否存在环,如果没有环直接返回。
470       *  在环中的一个节点处断开(函数结束之后需要恢复原来的链表结构)
471       *  然后就转化成了求两个单链表第一个相交节点的问题。
472       *  
473       */
474        //mhead->next->next->next->next->next = mhead->next->next->next;
475       Node *pF = getFirstNodeInCircle(mhead);
476       if (pF != NULL)
477           printf("The first Node in circle's value = %d\n",pF->key);
478       else printf("No circle\n");
479 
480      /*
481       * @给出一个单链表头指针head,和一个节点指针pToBeDeleted
482       *  要求用O(1)的时间爱你复杂度删除节点pToBeDeleted
483       *  可以把要删除的节点的下一个节点的数据复制到该节点,然后删除
484       *  下一个节点即可。
485       *  注意最后后一个节点的情况。这个时候只能用普通的方法来找到前一个节点。
486       */
487     
488       Node *pd = mhead->next->next->next;      
489       deleteNode(mhead, pd);
490       print(mhead); 
491     return 0;
492 }
493 
494 void init(Node *head){
495     Node *p = head;
496     
497     for (int i=0; i<5; i++){
498         p->next = new Node();
499         p->next->key = i+1;
500         p = p->next;
501     }
502 }
503 
504 void print(Node *head){
505     if (head->next == NULL)
506         return;
507     Node *p = head->next;
508     while (p != NULL){
509         printf("%d --> ",p->key);
510         p = p->next;
511     }
512     
513     puts("");
514 }

 

posted @ 2014-01-20 21:18  sky0917  阅读(866)  评论(0编辑  收藏  举报