简单的单链表(2)

01.#include <stdio.h>  
02.#include <stdbool.h>  
03.#include <stdlib.h>   
04.typedef struct ElementData  
05.{  
06.    int index;   
07.} Item ;   
08.  
09.typedef struct node   
10.{  
11.    Item item;  
12.    struct node * nextNode;  
13.} Node;  
14.  
15.typedef Node * linkList ;  
16.  
17.Node * CreateInsertNode(Item *item) ;  
18.  
19.  
20./*链表初始化   */   
21.bool initList(linkList *plist)  
22.{  
23.    *plist = (linkList)malloc(sizeof(Node));   
24.    if(*plist == NULL)  
25.    {  
26.        return false;  
27.    }  
28.    (*plist)->nextNode = NULL;  
29.    return true;      
30.}  
31.  
32./*返回链表长度  */  
33.int getListLength(linkList *plist)  
34.{  
35.    int length = 0;  
36.    Node * node = (*plist)->nextNode;  
37.    while(node != NULL)  
38.    {  
39.        length ++;  
40.        node = node->nextNode;     
41.    }  
42.    return length;  
43.}   
44.  
45./*返回在链表L中第一个与Item相同的元素的位序, 没有返回为0   */  
46.//两个结构体不能用 == 直接进行比较   
47.int locateElem(linkList  L, int item)  
48.{  
49.    int index = 0;  
50.    while(L)  
51.    {  
52.        index ++;   
53.        if(L->nextNode->item.index == item)  
54.        {  
55.            return index;   
56.        }  
57.        L = L->nextNode;   
58.    }     
59.    return index;  
60.}   
61.  
62./*返回在链表L的index-1个位置的元素  */  
63.//ndex-1个位置避免在index个位置插入的时候出错   
64.Node * getNode(linkList *L, int index)  
65.{  
66.    linkList p = (*L);  
67.      
68.    int j = 1;  
69.    while(p != NULL && j < index)  
70.    {  
71.        p = p->nextNode;  
72.        j++;   
73.    }  
74.          
75.    if(p == NULL || j > index)  
76.    {  
77.        fprintf(stderr, "要找的元素位置超出链表的长度.\n");  
78.        exit(EXIT_FAILURE);  
79.    }     
80.  
81.    return p;     
82.}   
83.  
84./*在链表L的index个位置插入item   */  
85.void listInsert(linkList *L, int index, Item *item)  
86.{     
87.    //得到index-1的元素   
88.    linkList currentNode;  
89.    currentNode = getNode(L, index);  
90.      
91.    //创建要插入的元素   
92.    linkList insertNode = CreateInsertNode(item) ;  
93.      
94.    //插入到链表中   
95.    insertNode->nextNode = currentNode->nextNode;  
96.    currentNode->nextNode = insertNode;        
97.}  
98.  
99./*把位于链表L的index个位置的元素删掉, 并用item返回其值      */  
100.void listDelect(linkList *L, int index, Item *item)  
101.{  
102.    //得到index-1的元素   
103.    linkList currentNode = getNode(L, index);  
104.      
105.    //删掉元素   
106.    linkList delectNode = currentNode->nextNode;  
107.    currentNode->nextNode = delectNode->nextNode;  
108.    *item = delectNode->item;  
109.    free(delectNode);  
110.}   
111.  
112./*头插入   */  
113.void CreateListHead(linkList *L, Item *item)  
114.{     
115.    //创建要插入的元素并初始化   
116.    Node *insertNode = CreateInsertNode(item) ;  
117.      
118.    //插入   
119.    linkList head = *L;  
120.    insertNode->nextNode = head->nextNode;  
121.    head->nextNode = insertNode;           
122.}  
123.  
124.  
125./*尾插入   */  
126.void CreateListTail(linkList *L, Item *item)  
127.{  
128.    //创建初始化要插入的元素   
129.    linkList insertNode = CreateInsertNode(item) ;  
130.      
131.    //找到最后一个元素   
132.    linkList list = (*L)->nextNode;  
133.    while(list->nextNode != NULL)  
134.    {   
135.        list = list->nextNode;   
136.    }   
137.      
138.    //插入   
139.    list->nextNode = insertNode;  
140.}   
141.  
142.  
143./*删除    */  
144.void ClearList(linkList *L)  
145.{  
146.    linkList list = (*L)->nextNode ;  
147.    linkList p ;  
148.    while( list != NULL )  
149.    {     
150.        p = list->nextNode;  
151.        free(list);  
152.        list = p;  
153.    }  
154.    (*L)->nextNode = NULL;  
155.}   
156.  
157./*输出链表  */  
158.void listTraverse(linkList *L)  
159.{  
160.    linkList p = (*L)->nextNode;  
161.    while(p)  
162.    {  
163.        printf("%d ,",p->item.index);  
164.        p = p->nextNode;  
165.    }  
166.}  
167.  
168./*创建要插入的元素  返回创建的node指针 */  
169.Node * CreateInsertNode(Item *item)  
170.{  
171.    Node * insertNode = (linkList)malloc(sizeof(Node));  
172.    if(insertNode == NULL)  
173.    {  
174.        fprintf(stderr,"尾插入错误");  
175.        exit(EXIT_FAILURE);  
176.    }   
177.    insertNode->item = *item ;  
178.    insertNode->nextNode = NULL;  
179.    return insertNode;  
180.}   
181.  
182./*单链表翻转/逆序  */  
183.//current始终保持在第一位,pnext与prev遍历并完成交换。  
184.void ListReverse(linkList *L)  
185.{  
186.    linkList current; //当前节点   
187.    linkList next;  //下一节点   
188.    linkList prev;  //上一节点   
189.      
190.    current = (*L)->nextNode;  
191.    next = current->nextNode;  
192.    current->nextNode = NULL;  
193.      
194.    while(next){  
195.        prev = next->nextNode;  
196.        next->nextNode = current;  
197.        current = next;  
198.        next = prev;  
199.    }  
200.    (*L)->nextNode = current;  
201.}   
202.  
203./*单链表翻转/逆序  */  
204.//current始终是原链表的第一个数,然后把pnext不断移动到首位。  
205.void ListReverse1(linkList *L)  
206.{  
207.    linkList current; //当前节点   
208.    linkList next;  //下一节点   
209.      
210.    current = (*L)->nextNode;  
211.      
212.    while(current->nextNode != NULL){  
213.        next = current->nextNode;  
214.        current->nextNode = next->nextNode;  
215.        next->nextNode = (*L)->nextNode;  
216.        (*L)->nextNode = next;   
217.    }  
218.}   
219.  
220./*单链表翻转/逆序  */  
221.//重新建立一个单链表newList,每次将L中的第一个结点放到newList后面  
222.linkList  ListReverse2(linkList *L)  
223.{  
224.    linkList newlist = CreateInsertNode( &((*L)->item) );   
225.    if( (*L)->nextNode == NULL)  
226.    {  
227.        return NULL;  
228.    }  
229.    linkList firstNode;   
230.    while( (*L)->nextNode )  
231.    {  
232.        firstNode = newlist->nextNode;  
233.        newlist->nextNode = (*L)->nextNode;  
234.        (*L)->nextNode = (*L)->nextNode->nextNode;  
235.        newlist->nextNode->nextNode = firstNode;            
236.    }  
237.    free(*L);  
238.    return newlist;   
239.}  
240.  
241.// 获取单链表倒数第N个结点值  
242.//建立两个指针,第一个先走n步,然后第2个指针也开始走,  
243.//两个指针步伐(前进速度)一致。当第一个结点走到链表末尾时,  
244.//第二个节点的位置就是我们需要的倒数第n个节点的值。   
245.void GetNthNodeFromBack(linkList *L, int n, Item *item)  
246.{  
247.    linkList list = (*L)->nextNode;  
248.    linkList last = (*L)->nextNode;  
249.    int index = 1;  
250.      
251.    while(list->nextNode != NULL && index < n)  
252.    {  
253.        index++;  
254.        list = list->nextNode;  
255.    }  
256.      
257.    if(list->nextNode == NULL || index > n)  
258.    {  
259.        fprintf(stderr, "要找的元素位置超出链表的长度.\n");  
260.        exit(EXIT_FAILURE);  
261.    }  
262.      
263.    while(list->nextNode != NULL)  
264.    {  
265.        list = list->nextNode;  
266.        last = last->nextNode;     
267.    }  
268.    *item = last->item;  
269.}  
270.  
271.//找到链表的中间节点   
272.void GetMidNode(linkList *L, Item *e)   
273.{  
274.    linkList first = *L;  
275.    linkList second = *L;   
276.    //first移动的速度是second的2倍   
277.    while(first->nextNode){  
278.        if(first->nextNode->nextNode){  
279.            first = first->nextNode->nextNode;  
280.            second = second->nextNode;  
281.        }else{  
282.            first = first->nextNode;  
283.        }     
284.    }  
285.      
286.    *e = second->item;  
287.}  
288.  
289.//删除重复的节点  
290.void RemoveDupNode(linkList *L)  
291.{  
292.    linkList first = *L; //用于遍历链表   
293.    linkList second ;  
294.    linkList delNode ;  
295.      
296.    while(first->nextNode){        
297.        second = first->nextNode;  //从first后面开始遍历   
298.        while(second->nextNode){  
299.            //判断节点是否相等            
300.            if(second->nextNode->item.index == first->nextNode->item.index){  
301.                //删除节点   
302.                delNode = second->nextNode;  
303.                second->nextNode = delNode->nextNode;               
304.                free(delNode);  
305.            }else{  
306.                second = second->nextNode;  
307.            }  
308.        }         
309.        first = first->nextNode;  
310.    }  
311.}   
312.  
313.//在单链表第n个位置建环  
314.//找到环入口点first,把最后的指针curr指向first   
315.void BulidListLoop(linkList *L, int num)  
316.{  
317.    linkList first = *L;  
318.    linkList curr ;  
319.      
320.    if(!first || num < 0){  
321.        fprintf(stderr,"建环失败.");  
322.        exit(EXIT_FAILURE);   
323.    }  
324.      
325.    for(int i = 0; i < num; i++){  
326.        if(!first){  
327.            fprintf(stderr,"建环失败,超出链表长度.");  
328.            exit(EXIT_FAILURE);   
329.        }  
330.        first = first->nextNode;  
331.    }  
332.      
333.    curr = first;  
334.      
335.    while(curr->nextNode){  
336.        curr = curr->nextNode;  
337.    }  
338.  
339.    curr->nextNode = first;    
340.}    
341.  
342.//判断链表是否有环  
343.//设两个工作指针,一个快一个慢,如果有环的话,它们会必然在某点相遇。  
344.int hasLoop(linkList *L)  
345.{  
346.    linkList first = *L;  
347.    linkList second = *L;  
348.      
349.    while(first && second && second->nextNode){  
350.        first = first->nextNode;  
351.        if(second->nextNode){  
352.            second = second->nextNode->nextNode;    
353.        }  
354.        if(first == second){  
355.            return 1;     
356.        }  
357.    }  
358.      
359.    return 0;  
360.}   
361.  
362.//判断链表是否有环  
363.//设两个工作指针p、q,p总是向前走,但q每次都从头开始走,  
364.//对于每个节点,看p走的步数是否和q一样  
365.int hasLoop1(linkList *L)  
366.{  
367.    linkList first = *L;  
368.    int setp = 0;  
369.      
370.    while(first){  
371.        setp ++;          
372.        linkList second = *L;  
373.        int index = 0;        
374.        while(second){  
375.            index ++;  
376.            if(first == second){  
377.                if(setp == index){ //步数相等说明没环   
378.                    break;  
379.                }else{  
380.                    return 1;     
381.                }     
382.            }  
383.            second = second->nextNode;  
384.        }  
385.        first = first->nextNode;  
386.    }  
387.      
388.    return 0;         
389.}  
390.  
391./*测试    */  
392.int main(void)  
393.{  
394.    linkList L;  
395.      
396.    if(!initList(&L))  
397.    {  
398.        fprintf(stderr,"初始化错误");  
399.        exit(EXIT_FAILURE);   
400.    }  
401.    Item item1 = {  
402.        item1.index = 5   
403.    };  
404.      
405.    Item item2 = {  
406.        item2.index = 6  
407.    };  
408.      
409.    Item item3 = {  
410.        item3.index = 7  
411.    };  
412.      
413.    Item item4 = {  
414.        item4.index = 6  
415.    };  
416.      
417.    Item item5 = {  
418.        item5.index = 9  
419.    };  
420.      
421.    Item item6 = {  
422.        item6.index = 4  
423.    };  
424.      
425.    listInsert(&L,1,&item1);   
426.    listInsert(&L,2,&item2);   
427.    listInsert(&L,3,&item3);   
428.    listInsert(&L,4,&item4);    
429.    CreateListHead(&L, &item5);  
430.    CreateListTail(&L, &item6);   
431.      
432.    int length = getListLength(&L);   
433.//  printf("length=%d\n",length);   
434.    listTraverse(&L);  //显示   
435./*   
436.    printf("\n"); 
437.    linkList n = ListReverse2(&L); //翻转  
438.    listTraverse(&n);  //显示  
439.     
440.     
441.    Item item5; 
442.    listDelect(&L,1,&item5); 
443.    int length1 = getListLength(&L);     
444.    printf("length1=%d\n",length1);  
445.    listTraverse(&L);    
446.*/  
447.    Node * getnode ;  
448.    getnode = getNode(&L, 2);   
449.    printf("\n%d\n", getnode->nextNode->item.index);  
450.  
451.    /* 
452.    Item  i; 
453.    GetNthNodeFromBack(&L, 2,&i) ; 测试单链表倒数第N个结点值 
454.    printf("\n"); 
455.    printf("%i",i.index); 
456.    */  
457.      
458.    /* 
459.    Item i; 
460.    GetMidNode(&L, &i); 测试中间节点  
461.    printf("\n"); 
462.     printf("%i",i.index); 
463.     */  
464.       
465.     /* 
466.     RemoveDupNode(&L); 测试删除重复节点  
467.     printf("\n"); 
468.      listTraverse(&L); 
469.      */  
470.        
471.      /* 
472.      BulidListLoop(&L,2); 
473.      int i = hasLoop1(&L); 测试建环 检测是否有环  
474.      printf("\n%d",i)  ; 
475.      */      
476.//  int index = locateElem(L,5);  
477.//  printf("%d",index);   
478.      
479.    ClearList(&L);    
480.    return 0;  
481.}  

 

posted @ 2013-03-16 15:40  chapterlin  阅读(111)  评论(0)    收藏  举报