【数据结构】单向链表,单向循环链表,双向循环链表

单向链表

头文件

 1 //@ author 成鹏致远
 2 //@ net http://infodown.tap.cn
 3 //@ qq 552158509
 4 //@ blog lcw.cnblogs.com
 5 
 6 #ifndef _LINKLIST_H
 7 #define _LINKLIST_H
 8 
 9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <stdbool.h>
12 
13 typedef int datatype;
14 
15 typedef struct node
16 {
17     datatype data;
18     struct node *next;
19 }linklist,*plinklist;
20 
21 extern void linklist_init(plinklist *plist);//初始化链表
22 extern void linklist_create(plinklist plist, int len);//从头结点创建链表
23 extern void linklist_create_tail(plinklist plist, int len);//从链表尾创建链表
24 extern void linklist_sort(plinklist plist);//实现链表的逆转
25 extern void linklist_show(plinklist plist);//显示链表
26 
27 #endif
View Code

单向链表

  1 //@ author 成鹏致远
  2 //@ net http://infodown.tap.cn
  3 //@ qq 552158509
  4 //@ blog lcw.cnblogs.com
  5 
  6 #include "linklist.h"
  7 
  8 void linklist_init(plinklist *plist)//初始化链表
  9 {
 10     *plist = (plinklist)malloc(sizeof(linklist));//申请空间
 11     if(*plist == NULL)
 12     {
 13         perror("malloc");
 14         exit(1);
 15     }
 16     (*plist)->next = NULL;//初始化为空
 17 }
 18 
 19 void linklist_create(plinklist plist, int len)//从头结点创建链表
 20 {
 21     plinklist new;
 22 
 23     while(len--)//创建len个结点
 24     {
 25         new = (plinklist)malloc(sizeof(linklist));//申请新空间
 26         if(new == NULL)
 27         {
 28             perror("malloc");
 29             exit(1);
 30         }
 31         new->data = len+1;//完成新结点的赋值
 32         
 33         //现在需要将新申请的结点和已有的结点链接在一起
 34         //注意是在头部插入
 35         new->next = plist->next;//将新申请的new结点插入到链表的最前面
 36         plist->next = new;
 37     }
 38 }
 39 
 40 void linklist_create_tail(plinklist plist, int len)//从链表尾创建链表
 41 {
 42     plinklist new;
 43     plinklist tail = plist;//tail表示链表的最后一个结点,在整个过程中,必须保证头结点(plist)的值不变
 44     int i;
 45 
 46     for(i=0; i<len; i++)
 47     {
 48         new = (plinklist)malloc(sizeof(linklist));//申请新空间
 49         if(new == NULL)
 50         {
 51             perror("malloc");
 52             exit(1);
 53         }
 54         new->data = i+1;
 55         
 56         //现在需要将新申请的结点和已有的结点链接在一起
 57         //注意是在尾部插入
 58         new->next = tail->next;//tail->next为空,new将成为新的尾结点
 59         tail->next = new;//将new结点插入到tail的后面
 60         tail = new;//tail后移,new成为新的尾结点
 61 
 62     }
 63 }
 64 
 65 void linklist_sort(plinklist plist)//实现链表的逆转
 66 {
 67     //思想
 68     //在创建时把最早申请的结点放到了最后面,最后申请的结点放到了最前面
 69     //所以逆转的过程就相当于创建时过程的重复执行,把最前面的又放到最后面
 70     //逆转过程和入栈|出栈是一样的
 71     //出栈|入栈只是为了方便理解
 72 
 73     plinklist p = plist->next;//所有的操作必须保证头结点不变,用p指向链表的第一个元素,负责逆转过程中原链表的的移位
 74     plinklist tem = NULL;//临时变量,负责将原链表元素转移到逆转后的链表(相当于:出栈后入栈)
 75 
 76     plist->next = NULL;//切断头结点与原链表的联系,以便重新建立链表
 77 
 78     while(p != NULL)//p辅助移位,相当于依次出栈
 79     {
 80         tem = p;//标记出栈的元素,即将入栈
 81         p = p->next;//移位,依次出栈
 82 
 83         //将出栈的元素加入到逆转后的链表,相当于再次入栈
 84         //插入过程和从头部创建链表过程一样
 85         tem->next = plist->next;
 86         plist->next = tem;//tem作为链表的第一个元素
 87 
 88     }
 89 }
 90 
 91 void linklist_show(plinklist plist)//显示链表
 92 {
 93     plinklist tem = plist->next;//同样是为了不改变头结点,所以需要临时结点指针
 94 
 95     while(tem != NULL)
 96     {
 97         printf("%d\t",tem->data);
 98         tem = tem->next;
 99     }
100     printf("\n");
101 }
View Code 

主文件

 1 //@ author 成鹏致远
 2 //@ net http://infodown.tap.cn
 3 //@ qq 552158509
 4 //@ blog lcw.cnblogs.com
 5 
 6 //用单向链表实现数据逆转
 7 //首先建立一个包含若干整数的单向链表,然后实现逆转
 8 
 9 #include "linklist.h"
10 
11 int main()
12 {
13     plinklist plist;
14     int length;
15 
16     linklist_init(&plist);//完成初始化_
17 
18     printf("Pls input the length of linklist:");
19     scanf("%d",&length);
20 #if 0
21     linklist_create(plist,length);//从头结点创建链表
22     linklist_show(plist);//显示链表
23     linklist_sort(plist);//逆转链表
24     linklist_show(plist);
25 
26 #else
27     printf("******************************************\n");
28     linklist_create_tail(plist,length);//从尾结点创建链表
29     linklist_show(plist);//显示链表
30     linklist_sort(plist);//逆转链表
31     linklist_show(plist);
32 
33 #endif
34 
35     return 0;
36 }
View Code

 


 

单向循环链表(josephu问题)

头文件 

 1 //@ author 成鹏致远
 2 //@ net http://infodown.tap.cn
 3 //@ qq 552158509
 4 //@ blog lcw.cnblogs.com
 5 
 6 #ifndef _LINKLIST_H
 7 #define _LINKLIST_H
 8 
 9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <stdbool.h>
12 
13 typedef int datatype;
14 
15 typedef struct node
16 {
17     datatype data;
18     struct node *next;
19 }linklist,*plinklist;
20 
21 
22 extern void josephu_init(plinklist *plist);//完成初始化
23 extern void josephu_create(plinklist *plist, int len);//创建链表
24 extern datatype josephu(plinklist plist);//完成数3出局
25 extern void josephu_show(plinklist plist);//显示链表
26 
27 
28 #endif
View Code

josephu

 1 //@ author 成鹏致远
 2 //@ net http://infodown.tap.cn
 3 //@ qq 552158509
 4 //@ blog lcw.cnblogs.com
 5 
 6 //用单向循环链表现实"数3出局"游戏(Josephu问题)
 7 //首先建立一个包含若干整数的单向循环链表,然后从第一个节点开始数,把数到3的那个节点删除
 8 //接着下一个节点开始数,数到3继续删除,以此类推,打印出最后剩余的那个节点
 9 
10 #include "linklist.h"
11 
12 void josephu_init(plinklist *plist)//完成初始化
13 {
14     #if 1//无头结点的初始化
15          *plist = NULL;
16     #else//有头结点的初始化
17          *plist = (plinklist)malloc(sizeof(linklist));
18          if(*plist == NULL)
19          {
20              perror("malloc");
21              exit(1);
22          }
23          (*plist)->next = *plist;
24     #endif
25 }
26 
27 void josephu_create(plinklist *plist, int len)//创建链表,因为初始化时没有头结点,所以参数需要传*plist
28 {
29     plinklist new;
30     plinklist tail;//尾指针,从链表尾部插入新结点
31     int i;
32 
33     for(i=0; i<len; i++)
34     {
35         if(0 == i)//因为无头结点,所以第一次也需要申请空间,并指向自己
36         {
37             *plist = (plinklist)malloc(sizeof(linklist));
38             if(*plist == NULL)
39             {
40                 perror("malloc");
41                 exit(1);
42             }
43             (*plist)->data = i+1;
44             (*plist)->next = *plist;//只有一个结点,指向自己
45 
46             tail = *plist;//初始化尾指针
47         }
48         else
49         {
50             new = (plinklist)malloc(sizeof(linklist));
51             if(new == NULL)
52             {
53                 perror("malloc");
54                 exit(1);
55             }
56             new->data = i+1;
57             //将新结点new和已有结点连在一起
58             //注意是在尾部插入
59             new->next = tail->next;
60             tail->next = new;//将new结点插入到tail后面
61             tail = new;//new变成新的尾结点
62         }
63     }
64 }
65 
66 datatype josephu(plinklist plist)//完成数3出局
67 {
68     plinklist head = plist;//指向每次变化的"头结点",每出局一个人,下一个人将变成头结点
69     plinklist tem;//临时指针,指向每次出局的人
70 
71     while(head != head->next)//只剩下一人时退出循环
72     {
73         tem = head->next->next;//tem将出局
74         head->next->next = tem->next;//tem->next将是下一个"头结点"
75         head = tem->next;//新"头结点"
76 
77         printf("%d\t",tem->data);
78         free(tem);//tem出局
79     }
80     return head->data;
81 }
82 
83 void josephu_show(plinklist plist)//显示链表
84 {
85     plinklist tem = plist;//保证头结点不变
86     while(tem != NULL && tem->next != plist)//循环遍历
87     {
88         printf("%d\t",tem->data);
89         tem = tem->next;
90     }
91     //注意最后一次循环是tem->next = plist,所以最后一个结点并没有输出
92     printf("%d\n",tem->data);
93 
94 }
View Code

主文件

 1 //@ author 成鹏致远
 2 //@ net http://infodown.tap.cn
 3 //@ qq 552158509
 4 //@ blog lcw.cnblogs.com
 5 
 6 //用单向循环链表现实"数3出局"游戏(Josephu问题)
 7 //首先建立一个包含若干整数的单向循环链表,然后从第一个节点开始数,把数到3的那个节点删除
 8 //接着下一个节点开始数,数到3继续删除,以此类推,打印出最后剩余的那个节点
 9 
10 #include "linklist.h"
11 
12 int main()
13 {
14     plinklist plist;
15     datatype result;
16     int len;
17 
18     josephu_init(&plist);//完成初始化
19 
20     printf("Pls input the length of josephu:");
21     scanf("%d",&len);
22 
23     josephu_create(&plist,len);//创建josephu链表
24     josephu_show(plist);//显示josephu链表
25     
26     result = josephu(plist);//解决方案
27     printf("\nThe last is %d\n",result);
28 
29     return 0;
30 }
View Code

 

 


 双向循环链表

头文件

 1 //@ author 成鹏致远
 2 //@ net http://infodown.tap.cn
 3 //@ qq 552158509
 4 //@ blog lcw.cnblogs.com
 5 
 6 #ifndef _DOUBLELIST_H
 7 #define _DOUBLELIST_H
 8 
 9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <stdbool.h>
12 
13 typedef int datatype;
14 
15 typedef struct node
16 {
17     datatype data;
18     struct node *next,*prior;
19 }double_list,*double_plist;
20 
21 extern void double_init(double_plist *plist);//双向链表的初始化
22 extern void double_sort(double_plist plist);//完成双向链表的奇数升序偶数降序排列
23 extern void double_create(double_plist plist, int len);//头插法创建双向链表
24 extern void double_show(double_plist plist);//显示双向链表
25 
26 #endif
View Code

 双向循环链表

 1 //@ author 成鹏致远
 2 //@ net http://infodown.tap.cn
 3 //@ qq 552158509
 4 //@ blog lcw.cnblogs.com
 5 
 6 //用双向循环链表实现顺序递增存储若干个自然数
 7 //比如输入一个整数10,则建立一个双向循环链表,里面的每个节点分别存放1,2,3,4,5,6,7,8,9,10
 8 //然后通过某些操作,将其重新排列成1,3,5,7,9,10,8,6,4,2,即奇数升序偶数降序,并在屏幕上打印出来
 9 
10 #include "double_list.h"
11 
12 void double_init(double_plist *plist)//双向链表的初始化
13 {
14     *plist = (double_plist)malloc(sizeof(double_list));
15     if(*plist == NULL)
16     {
17         perror("malloc");
18         exit(1);
19     }
20 
21     (*plist)->next = (*plist)->prior = *plist;//双向链表的前后指针都指向自己
22 
23 }
24 
25 void double_sort(double_plist plist)//完成双向链表的奇数升序偶数降序排列
26 {
27     double_plist pnext = plist->next;//指向链表的第一个节点
28     double_plist prior = plist->prior;//指向链表的最后一个节点
29     double_plist tem = NULL;//临时指针,用于辅助定位将被移动的节点
30 
31     while(pnext != prior)//没有到达链表尾
32     {
33         if(pnext->data%2 !=0)//为奇数,直接跳过
34             pnext = pnext->next;
35         else//为偶数,将pnext移动到偶数后面一位奇数位置,用tem指向回去辅助移动偶数链表节点
36         {
37             pnext = pnext->next;
38 
39             //将pnext前面的节点剪切出来
40             tem = pnext->prior;//tem指向要被移动的节点
41             pnext->prior = tem->prior;//将奇数节点前向指针连接起来
42             tem->prior->next = pnext;//将奇数节点后向指针连接起来
43 
44             //将偶数节点(tem)插入到链表尾(prior)
45             tem->next = prior->next;//tem将成为新的尾结点
46             prior->next->prior = tem;//链表首尾相连
47             //prior和新的尾结点tem相连
48             tem->prior = prior;
49             prior->next = tem;
50         }
51     }
52 }
53 
54 void double_create(double_plist plist, int len)//头插法创建双向链表
55 {
56     double_plist new;
57     while(len--)//创建len个节点
58     {
59         new = (double_plist)malloc(sizeof(double_list));
60         if(new == NULL)
61         {
62             perror("malloc");
63             exit(1);
64         }
65         new->data = len+1;
66 
67         //向plist后面插入一个新的节点
68         //双向链表的头插法
69         new->next = plist->next;
70         plist->next->prior = new;
71         new->prior = plist;
72         plist->next = new;
73     }
74 }
75 
76 void double_show(double_plist plist)//显示双向链表
77 {
78     double_plist tem = plist->next;//保证头结点不变
79 
80     while(tem != plist)//遍历一个循环
81     {
82         printf("%d\t",tem->data);
83         tem = tem->next;
84     }
85     printf("\n");
86 }
View Code

主文件 

 1 //@ author 成鹏致远
 2 //@ net http://infodown.tap.cn
 3 //@ qq 552158509
 4 //@ blog lcw.cnblogs.com
 5 
 6 //用双向循环链表实现顺序递增存储若干个自然数
 7 //比如输入一个整数10,则建立一个双向循环链表,里面的每个节点分别存放1,2,3,4,5,6,7,8,9,10
 8 //然后通过某些操作,将其重新排列成1,3,5,7,9,10,8,6,4,2,即奇数升序偶数降序,并在屏幕上打印出来
 9 
10 #include "double_list.h"
11 
12 int main()
13 {
14     double_plist plist;
15     int len;
16 
17     double_init(&plist);//双向链表初始化
18 
19     printf("Pls input the length of double list:");
20     scanf("%d",&len);
21 
22     double_create(plist,len);//创建双向链表
23     double_show(plist);//显示双向链表
24 
25     double_sort(plist);//完成奇数升序偶数降序排序
26     double_show(plist);
27 
28     return 0;
29 }
View Code

 

 

posted @ 2013-08-03 17:57  Leo.cheng  阅读(1804)  评论(0编辑  收藏  举报