C语言链表

一,认识

1,引入,数组的分类,静态数组(int arr[20]容易空间溢出或者浪费),动态数组(malloc合理利用空间但是不能快捷的插入或者删除数据,会涉及到大量的数据移动)

链表是一种物理量储存上非连续,按逻辑顺序通过链表中的指针链接,是一种线性储存结构

链表由一系列节点组成(链表中每个元素成为一个节点),节点包括两个部分,数据域和指针域,指针域储存下一个节点的地址

C语言链表_第1张图片

二、静态链表

链表的定义,通过结构体实现

1 typedef struct stu
2 {
3  //数据域(自定义)
4  int num;
5  char name[32];
6  float score;
7
8  //指针域 保存下一个节点的地址
9  struct stu *next;
10 }STU;
11
12 void test07()
13 {
14  //链表头
15  STU *head = NULL;
16  //遍历链表
17  STU *pb = NULL;
18  STU data1 = {100,"德玛", 59};
19  STU data2 = {101,"小炮", 89};
20  STU data3 = {102,"小法", 79};
21  STU data4 = {103,"盲僧", 99};
22  STU data5 = {104,"快乐风男", 39};
23
24  head = &data1;
25  data1.next = &data2;
26  data2.next = &data3;
27  data3.next = &data4;
28  data4.next = &data5;
29  data5.next = NULL;
30
31  pb = head;
32  while(pb != NULL)
33  {
34  printf("%d %s %f\n", pb‐>num,pb‐>name,pb‐>score);
35  pb=pb‐>next;//pb指向下一个节点
36  }
37 }

三、动态链表       

思路,先main中写出程序框架,先调出帮助菜单,接受指令,判断指令调用相应函数,有help,insert,print,search,delete,free,quit

链表的插入(重点)

1,头部之前插入

C语言链表_第2张图片

分类 讨论

C语言链表_第3张图片

2,在链表的尾部插入

C语言链表_第4张图片

 //链表的尾部插入
2 STU* insert_link(STU *head, STU tmp)
3 {
4  //1、申请待插入的节点
5  STU *pi = (STU *)calloc(1,sizeof(STU));
6  if(pi == NULL)
7  {
8  perror(calloc);
9  return head;
10  }
11
12  //2、将tmp的数据 赋值到 *pi
13  *pi = tmp;
14  pi‐>next = NULL;
15
16  //3、将节点插入到链表的尾部
17  if(head == NULL)//链表不存在
18  {
19  head = pi;
20  return head;
21  }
22  else//链表存在
23  {
24  //a、寻找链表的尾节点
25  STU *pb = head;
26  while(pb‐>next != NULL)//如果不是尾节点
27  pb = pb‐>next;//pb就指向下一个节点
28
29  //b、用尾结点 pb 链接上 插入的节点pi
30  pb‐>next = pi;
31  return head;
32  }
33
34  return head;
35 }

3,链表的有序插入 

C语言链表_第5张图片

1 //链表的有序插入 以num的顺序为准(小‐‐‐>大)
2 STU* insert_link(STU *head, STU tmp)
3 {
4  //1、给待插入的节点pi 申请 堆区空间
5  STU *pi = (STU *)calloc(1,sizeof(STU));
6  if(pi == NULL)
7  {
8  perror("calloc");
9  return head;
10  }
11
12  //2、将tmp的内容 赋值给 *pi
13  *pi = tmp;
14  pi‐>next = NULL;
15
16  //3、链表节点pi的插入
17  if(head == NULL)//链表不存在
18  {
19  head = pi;
20  return head;
21  }
22  else//存在
23  {
24  //a、寻找插入点
25  STU *pb = head, *pf = head;
26  while(pb‐>num < pi‐>num && pb‐>next != NULL)
27  {
28  pf = pb;
29  pb = pb‐>next;
30  }
31
32  //b、插入点的判断
33  if(pb‐>num >= pi‐>num)//头部 中部插入
34  {
35  if(pb == head)//头部之前插入
36  {
37  pi‐>next = head;
38  head = pi;
39  return head;
40  }
41  else//中部插入
42  {
43  pf‐>next = pi;
44  pi‐>next = pb;
45  return head;
46  }
47  }
48  else//尾部插入
49  {
50  pb‐>next = pi;
51  return head;
52  }
53  }
54  return head;
55 }

链表的查询 

C语言链表_第6张图片

 

1 STU* search_link(STU *head, char *name)
2 {
3  //1、判断链表是否存在
4  if(head == NULL)//不存在
5  {
6  printf("link not found\n");
7  return NULL;
8  }
9  else//链表存在
10  {
11  STU *pb = head;
12
13  //逐个将节点中的name 和 name比较 如果不相等 pb=pb‐>next
14  while(strcmp(pb‐>name,name)!=0 && pb‐>next != NULL)
15  pb = pb‐>next;
16
17  //判断是否找到
18  if(strcmp(pb‐>name,name)==0)//找到
19  return pb;
20  else//没找到
21  return NULL;
22  }
23
24  return NULL;
25 }

删除链表制定节点

C语言链表_第7张图片

1 STU* detele_link(STU *head,char *name)
2 {
3  //1、判断链表是否存在
4  if(head == NULL)//不存在
5  {
6  printf("link not found\n");
7  return head;
8  }
9  else//存在
10  {
11  //2、寻找删除点
12  STU *pf=head, *pb = head;
13  while(strcmp(pb‐>name,name)!=0 && pb‐>next != NULL)
14  {
15  pf = pb;
16  pb = pb‐>next;
17  }
18
19  //3、找到删除点
20  if(strcmp(pb‐>name,name)==0)//找到删除点
21  {
22  //4、判断删除的位置
23  if(pb == head)//删除头结点
24  {
25  head = pb‐>next;
26  free(pb);
27
28  }
29  else//中部 或 尾部节点
30  {
31  pf‐>next = pb‐>next;
32  free(pb);
33  }
34  printf("已成功删除%s的相关节点\n",name);
35  return head;
36  }
37  else//没找到删除点
38  {
39  printf("链表中没有%s相关的数据节点信息\n",name);
40  }
41  }
42  return head;
43 }

链表的释放

 

1 STU* free_link(STU *head)
2 {
3  //判断链表是否存在
4  if(head == NULL)
5  {
6  printf("link not found\n");
7  return head;
8  }
9  else//链表存在
10  {
11  STU *pb = head;
12
13  //逐个节点释放
14  while(pb != NULL)
15  {
16  //head保存下一个节点的位置
17  head = pb‐>next;
18  //释放pb指向的节点
19  free(pb);
20  //pb 指向 head
21  pb = head;
22  }
23
24  printf("链表已经释放完毕\n");
25  return head;
26  }
27
28  return head;
29 }

小结


链表的插入:头部之前插入     尾部插入    有序插入
1、为插入的节点pi申请空间
2、将tmp的值赋值给*pi       *pi = tmp
3、判断链表是否 存在
    3-1:不存在      head = pi
    3-2:   存在   (尾部插入   有序插入) 寻找插入点   安装具体的位置 插入节点
链表的遍历:
1、判断链表是否存在
1-1:不存在  不执行任何操作
1-2:存在     逐个节点遍历  注意 别越界。
链表的查询:
1、判断链表是否存在
1-1:不存在  不执行任何操作
1-2:存在     逐个节点比较   比较成功返回位置    注意 别越界。
链表节点的删除:
1、判断链表是否存在
1-1:不存在  不执行任何操作
1-2:存在     逐个节点比较   删除指定节点    注意 别越界。
释放链表:
1、判断链表是否存在
1-1:不存在  不执行任何操作
1-2:存在     逐个节点节点释放    注意 别越界

链表的逆序

C语言链表_第8张图片

1 STU* reverse_link(STU *head)
2 {
3  //判断链表是否存在
4  if(head == NULL)
5  {
6  printf("link not founf\n");
7  return head;
8  }
9  else//链表存在
10  {
11  //int *p,num;//p为int * , num为int
12  STU *pb,*pr;//pb为STU * , pr为STU *
13
14  //pb保存head‐>next(原因head‐>next会置NULL)
15  pb = head‐>next;
16  //将head‐>next置NULL (原因:头节点变尾节点)
17  head‐>next = NULL;
18
19  while(pb != NULL)
20  {
21  //pr保存pb‐>next (原因:pb‐>next会指向head)
22  pr = pb‐>next;
23
24  //pb‐>next 指向 head (原因:逆转方向)
25  pb‐>next = head;
26
27  //保存 逆转方向的代码 可以重复 执行
28  head = pb;
29  pb = pr;
30  }
31
32  return head;
33  }
34  return head;
35 }

链表的排序

引入,选择排序(用数组实现)

C语言链表_第9张图片

1 #include
2 int main()
3 {
4  int arr[10]={0};
5  int n = sizeof(arr)/sizeof(arr[0]);
6  int i=0,j=0,min=0;
7
8  printf("请输入%d个int数据\n",n);
9  for(i=0;i arr[j])
20  min = j;
21  }
22
23  if(min != i)
24  {
25  int tmp = 0;
26  tmp = arr[i];
27  arr[i]=arr[min];
28  arr[min]=tmp;
29  }
30
31  }
32
33  for(i=0;i

 

链表的排序(选择排序)

C语言链表_第10张图片

1 void sort_link(STU *head)
2 {
3  //1、判断链表是否存在
4  if(NULL == head)
5  {
6  printf("link not found\n");
7  return;
8  }
9  else
10  {
11  STU *p_i = head;//i=0
12  while(p_i‐>next != NULL)//inext;//j = min+1
16  while(p_j != NULL)//jnum > p_j‐>num)//if(arr[min] > arr[j])
21  p_min = p_j;//min = j
22  p_j = p_j‐>next;//j++
23
24  }
25
26  if(p_min != p_i)//min != i
27  {
28  //只交换数据域(1、节点内容整体交换 2、只交换指针域)
29  //1、节点内容整体交换(数据域交换第1次 指针域交换第1次)
30  STU tmp;
31  tmp = *p_i;
32  *p_i = *p_min;
33  *p_min = tmp;
34
35  //2、只交换指针域(指针域交换第2次)
36  tmp.next = p_i‐>next;
37  p_i‐>next = p_min‐>next;
38  p_min‐>next = tmp.next;
39  }
40
41
42  p_i = p_i‐>next;//i++
43  }
44
45  }
46
47 }

综合案例(小程序—未完待续)

1、布局整个程序框架
main.c
1 #include
2
3 void stu_help(void);
4 int main(int argc,char *argv[])
5 {
6  stu_help();
7
8  while(1)
9  {
10  char cmd[32]="";
11  printf("请输入操作指令:");
12
13  scanf("%s",cmd);
14  if(strcmp(cmd,"help") == 0)
15  {
16  stu_help();
17  }
18  else if(strcmp(cmd,"insert") == 0)
19  {
20  printf("‐‐‐‐‐insert‐‐‐‐‐‐\n");
21  }
22  else if(strcmp(cmd,"print") == 0)
23  {
24  printf("‐‐‐‐‐print‐‐‐‐‐‐\n");
25  }
26  else if(strcmp(cmd,"search") == 0)
27  {
28  printf("‐‐‐‐‐search‐‐‐‐‐‐\n");
29  }
30  else if(strcmp(cmd,"delete") == 0)
31  {
32  printf("‐‐‐‐‐delete‐‐‐‐‐‐\n");
33  }
34  else if(strcmp(cmd,"free") == 0)
35  {
36  printf("‐‐‐‐‐free‐‐‐‐‐‐\n");
37  }
38  else if(strcmp(cmd,"quit") == 0)
39  {
40  break;
41  }
42
43  }
44  return 0;
45 }
46
47 void stu_help(void)
48 {
49  printf("################################\n");
50  printf("#help:打印帮助信息 #\n");
51  printf("#insert:插入链表节点 #\n");
52  printf("#print:遍历链表节点信息 #\n");
53  printf("#search:查询链表节点 #\n");
54  printf("#delete:删除链表节点 #\n");
55  printf("#free:释放链表 #\n");
56  printf("#quit:退出 #\n");
57  printf("################################\n");
58  return;
59 }
2、链表插入节点 之 头部之前插入。
原理分析图:
案例:
main.c
1 #include
2 #include
3 #include "link.h"
4 void stu_help(void);
5 int main(int argc,char *argv[])
6 {
7  //定义一个链表头 注意 一定要赋值为NULL
8  STU *head=NULL;
9
10  stu_help();
11
12  while(1)
13  {
14  char cmd[32]="";
15  printf("请输入操作指令:");
16
17  scanf("%s",cmd);
18  if(strcmp(cmd,"help") == 0)
19  {
20  stu_help();
21  }
22  else if(strcmp(cmd,"insert") == 0)
23  {
24  STU tmp;
25  printf("请输入需要插入的数据:");
26  scanf("%d %s %f",&tmp.num, tmp.name, &tmp.score);
27
28  //将tmp数据 插入到head所指向的链表中
29  head = insert_link(head, tmp);
30  }
31  else if(strcmp(cmd,"print") == 0)
32  {
33  print_link(head);
34  }
35  else if(strcmp(cmd,"search") == 0)
36  {
37  printf("‐‐‐‐‐search‐‐‐‐‐‐\n");
38  }
39  else if(strcmp(cmd,"delete") == 0)
40  {
41  printf("‐‐‐‐‐delete‐‐‐‐‐‐\n");
42  }
43  else if(strcmp(cmd,"free") == 0)
44  {
45  printf("‐‐‐‐‐free‐‐‐‐‐‐\n");
46  }
47  else if(strcmp(cmd,"quit") == 0)
48  {
49  break;
50  }
51
52  }
53  return 0;
54 }
55
56 void stu_help(void)
57 {
58  printf("################################\n");
59  printf("#help:打印帮助信息 #\n");
60  printf("#insert:插入链表节点 #\n");
61  printf("#print:遍历链表节点信息 #\n");
62  printf("#search:查询链表节点 #\n");
63  printf("#delete:删除链表节点 #\n");
64  printf("#free:释放链表 #\n");
65  printf("#quit:退出 #\n");
66  printf("################################\n");
67  return;
68 }
link.c
1 #include
2 #include//calloc
3 #include"link.h"
4 STU* insert_link(STU *head, STU tmp)
5 {
6
7  //1、从堆区申请一个待插入的节点空间
8  STU *pi = (STU *)calloc(1,sizeof(STU));
9  if(pi == NULL)
10  {
11  perror("calloc");
12  return head;
13  }
14
15  //2、将tmp的值 赋值 给*pi
16  *pi = tmp;
17  pi‐>next = NULL;//注意
18
19  //3、将pi插入到链表中
20  if(head == NULL)//链表不存在
21  {
22  head = pi;
23  //return head;
24  }
25  else//链表存在(头部之前插入)
26  {
27  //1、让pi 指向就的头
28  pi‐>next = head;
29
30  //2、head指向新的头节点
31  head = pi;
32
33  //return head;
34  }
35
36  return head;
37 }
38
39 void print_link(STU *head)
40 {
41  if(head == NULL)//链表不存在
42  {
43  printf("link not find\n");
44  return;
45  }
46  else
47  {
48  STU *pb = head;
49  while(pb != NULL)
50  {
51  printf("%d %s %f\n", pb‐>num, pb‐>name,pb‐>score);
52  //pb指向下一个节点
53  pb = pb‐>next;
54  }
55
56  }
57
58  return;
59 }
link.h
1 //防止头文件重复包含
2 #ifndef __LINK_H__
3 #define __LINK_H__
4 //链表节点类型 定义
5 typedef struct stu
6 {
7  //数据域
8  int num;
9  char name[32];
10  float score;
11
12  //指针域
13  struct stu *next;
14 }STU;
15
16 extern STU* insert_link(STU *head, STU tmp);
17 extern void print_link(STU *head);
18 #endif
19

小结

1,设计程序连续接受指令,用个while(1){        },接收键盘输入指令并跳转相应函数,用if  else语句条件为(strcmp==0)

        2,链表插入之头部插入流程

                1,STU temp,先定义一个临时结构体,并获取键盘输入给他赋值

                2,从堆区申请一个待插入的节点空间STU *pi = (STU *)calloc(1,sizeof(STU));

                3,将temp的值赋给*pi,并注意pi.next=NULL

                4,将pi插入到链表中——头部之前插入

                        1,链表不存在(head==NULL)直接head=pi        return

                        2,链表存在,头部之前插入

                                1,让pi指向旧的头节点pi->next=head

                                2,head指向新的头节点,head=pi        return  head

            3,遍历链表,第一步先判断链表是否存在,第二部,STU *pb=head,while(pb!=NULL){printf    然后pb=pb->nextpb指向下一个节点}

双向循环链表

认识双向循环链表

C语言链表_第11张图片

双向循环链表插入 

C语言链表_第12张图片

1 //头部之前插入
2 STU* insert_link(STU *head, STU tmp)
3 {
4  //1、为插入的节点pi申请空间
5  STU *pi = (STU *)calloc(1,sizeof(STU));
6  //2、将tmp的值 赋值给 *pi
7  *pi = tmp;
8
9  //3、判断链表是否存在
10  if(head == NULL)//链表不存在
11  {
12  head = pi;
13  pi‐>next = head;
14  pi‐>pre = head;
15  }
16  else//链表存在(头部之前插入)
17  {
18  pi‐>next = head;
19  pi‐>pre = head‐>pre;
20  head‐>pre‐>next = pi;
21  head‐>pre = pi;
22  head = pi;
23  }
24
25  return head;
26 }

案例 

1 #include
2 #include
3 #include
4 //定义一个双向循环链表的节点类型
5 typedef struct stu
6 {
7  //数据域
8  int num;
9  char name[32];
10  int age;
11
12  //指针域
13  struct stu *next;//指向下一个节点
14  struct stu *pre;//指向前一个节点
15 }STU;
16
17 extern STU* insert_link(STU *head, STU tmp);
18 extern void print_link(STU *head);
19 extern STU* search_link(STU *head, char *name);
20 extern STU* delete_link(STU *head, int num);
21 extern STU* free_link(STU *head);
22
23 int main(int argc,char *argv[])
24 {
25  char name[32]="";
26  int num = 0;
27  int n =0;//保存学生的个数
28  int i=0;
29  STU *head = NULL;
30  STU *ret = NULL;
31
32  printf("请输入学员的个数:");
33  scanf("%d", &n);
34
35  for(i=0;inum, ret‐>name,ret‐>age);
62  }
63 #endif
64  //删除指定节点 num
65  printf("请输入要删除的学号:");
66  scanf("%d", &num);
67  head = delete_link(head, num);
68
69  //遍历整个链表
70  print_link(head);
71
72  //释放整个链表
73  head = free_link(head);
74
75  //遍历整个链表
76  print_link(head);
77
78  return 0;
79 }
80
81 //头部之前插入
82 STU* insert_link(STU *head, STU tmp)
83 {
84  //1、为插入的节点pi申请空间
85  STU *pi = (STU *)calloc(1,sizeof(STU));
86  //2、将tmp的值 赋值给 *pi
87  *pi = tmp;
88
89  //3、判断链表是否存在
90  if(head == NULL)//链表不存在
91  {
92  head = pi;
93  pi‐>next = head;
94  pi‐>pre = head;
95  }
96  else//链表存在(头部之前插入)
97  {
98  pi‐>next = head;
99  pi‐>pre = head‐>pre;
100  head‐>pre‐>next = pi;
101  head‐>pre = pi;
102  head = pi;
103  }
104
105  return head;
106 }
107
108 #if 1
109 void print_link(STU *head)
110 {
111  //判断链表是否存在
112  if(head == NULL)
113  {
114  printf("link not found\n");
115  return;
116  }
117  else//链表存在
118  {
119  STU *pb = head;
120  do
121  {
122  //访问节点内容
123  printf("num=%d, name=%s, age=%d\n", pb‐>num,pb‐>name,pb‐>age);
124  //pb指向下一个节点
125  pb = pb‐>next;
126  }while(pb != head);
127  }
128  return;
129 }
130 #endif
131 #if 0
132 void print_link(STU *head)
133 {
134  //判断链表是否存在
135  if(head == NULL)
136  {
137  printf("link not found\n");
138  }
139  else//链表存在
140  {
141  STU *pb = head;//pb指向头结点
142  STU *pf = head‐>pre;//pf指向了尾节点
143
144  do
145  {
146  if(pb == pf)//相遇 只需要打印pf或pb中任何一个信息就够了
147  {
148  printf("num=%d,name=%s,age=%d\n", pb‐>num,pb‐>name,pb‐>age);
149  break;
150  }
151  printf("num=%d,name=%s,age=%d\n", pb‐>num,pb‐>name,pb‐>age);
152  printf("num=%d,name=%s,age=%d\n", pf‐>num,pf‐>name,pf‐>age);
153
154  pb = pb‐>next;//next方向的移动
155  pf = pf‐>pre;//pre方向的移动
156  }while( pb‐>pre != pf );//pf和pb不能 擦肩而过
157
158  }
159 }
160
161 #endif
162
163 STU* search_link(STU *head, char *name)
164 {
165  //判断链表是否存在
166  if(head == NULL)
167  {
168  return NULL;
169  }
170  else//链表存在
171  {
172  STU *pb = head;//指向头结点
173  STU *pf = head‐>pre;//指向的是尾节点
174  printf("pb = %p\n", pb);
175  printf("pf = %p\n", pf);
176  printf("pb‐>pre = %p\n", pb‐>pre);
177
178
179  while( (strcmp(pb‐>name,name) != 0) && (strcmp(pf‐>name,name)!=0) && (p
b != pf) )
180  {
181  printf("##pb‐>name=%s##\n",pb‐>name);
182  printf("##pf‐>name=%s##\n",pf‐>name);
183  pb=pb‐>next;//next方向移动
184  pf=pf‐>pre;//pf方向移动
185
186  if(pb‐>pre == pf)
187  {
188  break;
189  }
190  }
191
192  if(strcmp(pb‐>name,name) == 0)
193  {
194
195  return pb;
196  }
197  else if(strcmp(pf‐>name,name)==0)
198  {
199  return pf;
200  }
201  }
202
203  return NULL;
204 }
205
206 STU* delete_link(STU *head, int num)
207 {
208  //判断链表是否存在
209  if(head == NULL)
210  {
211  printf("link not found\n");
212  return head;
213  }
214  else
215  {
216  STU *pb = head;//指向头节点
217  STU *pf = head‐>pre;//指向尾节点
218
219  //逐个节点寻找删除点
220  while((pb‐>num != num) && (pf‐>num != num) && (pf != pb))
221  {
222  pb = pb‐>next;//next方向移动
223  pf = pf‐>pre;//pre方向移动
224  if(pb‐>pre == pf)
225  break;
226  }
227
228  if(pb‐>num == num)//删除pb指向的节点
229  {
230
231  if(pb == head)//删除头节点
232  {
233  if(head == head‐>next)
234  {
235  free(pb);
236  head = NULL;
237  }
238  else
239  {
240  head‐>next‐>pre = head‐>pre;
241  head‐>pre‐>next = head‐>next;
242  head = head‐>next;
243  free(pb);
244  }
245
246  }
247  else//删除中尾部节点
248  {
249  pb‐>pre‐>next = pb‐>next;
250  pb‐>next‐>pre = pb‐>pre;
251  free(pb);
252  }
253  }
254  else if(pf‐>num == num)//删除pf指向的节点
255  {
256
257  if(pf == head)//删除头节点
258  {
259  if(head == head‐>next)
260  {
261  free(pf);
262  head = NULL;
263  }
264  else
265  {
266  head‐>next‐>pre = head‐>pre;
267  head‐>pre‐>next = head‐>next;
268  head = head‐>next;
269  free(pf);
270  }
271  }
272  else//删除中尾部节点
273  {
274  pf‐>pre‐>next = pf‐>next;
275  pf‐>next‐>pre = pf‐>pre;
276  free(pf);
277  }
278  }
279  else
280  {
281  printf("未找到%d相关的节点信息",num);
282  }
283  }
284
285  return head;
286 }
287
288 STU* free_link(STU *head)
289 {
290  if(head == NULL)//链表为空
291  {
292  printf("link not found\n");
293  return NULL;
294  }
295  else//链表存在
296  {
297  STU *pb = head;
298  STU *tmp;
299  do
300  {
301  tmp = pb;
302  pb = pb‐>next;
303  free(tmp);
304  }while(pb != head);
305  }
306
307  return NULL;
308 }

链表的遍历

单向遍历

1 void print_link(STU *head)
2 {
3  //判断链表是否存在
4  if(head == NULL)
5  {
6  printf("link not found\n");
7  return;
8  }
9  else//链表存在
10  {
11  STU *pb = head;
12  do
13  {
14  //访问节点内容
15  printf("num=%d, name=%s, age=%d\n", pb‐>num,pb‐>name,pb‐>age);
16  //pb指向下一个节点
17  pb = pb‐>next;
18  }while(pb != head);
19  }
20  return;
21 }

双向遍历

1 void print_link(STU *head)
2 {
3  //判断链表是否存在
4  if(head == NULL)
5  {
6  printf("link not found\n");
7  }
8  else//链表存在
9  {
10  STU *pb = head;//pb指向头结点
11  STU *pf = head‐>pre;//pf指向了尾节点
12
13  do
14  {
15  if(pb == pf)//相遇 只需要打印pf或pb中任何一个信息就够了
16  {
17  printf("num=%d,name=%s,age=%d\n", pb‐>num,pb‐>name,pb‐>age);
18  break;
19  }
20  printf("num=%d,name=%s,age=%d\n", pb‐>num,pb‐>name,pb‐>age);
21  printf("num=%d,name=%s,age=%d\n", pf‐>num,pf‐>name,pf‐>age);
22
23  pb = pb‐>next;//next方向的移动
24  pf = pf‐>pre;//pre方向的移动
25  }while( pb‐>pre != pf );//pf和pb不能 擦肩而过
26
27  }
28 }

双向链表的查找

1 STU* search_link(STU *head, char *name)
2 {
3  //判断链表是否存在
4  if(head == NULL)
5  {
6  return NULL;
7  }
8  else//链表存在
9  {
10  STU *pb = head;//指向头结点
11  STU *pf = head‐>pre;//指向的是尾节点
12  printf("pb = %p\n", pb);
13  printf("pf = %p\n", pf);
14  printf("pb‐>pre = %p\n", pb‐>pre);
15
16
17  while( (strcmp(pb‐>name,name) != 0) && (strcmp(pf‐>name,name)!=0) && (p
b != pf) )
18  {
19  printf("##pb‐>name=%s##\n",pb‐>name);
20  printf("##pf‐>name=%s##\n",pf‐>name);
21  pb=pb‐>next;//next方向移动
22  pf=pf‐>pre;//pf方向移动
23
24  if(pb‐>pre == pf)
25  {
26  break;
27  }
28  }
29
30  if(strcmp(pb‐>name,name) == 0)
31  {
32
33  return pb;
34  }
35  else if(strcmp(pf‐>name,name)==0)
36  {
37  return pf;
38  }
39  }
40
41  return NULL;
42 }

双向链表删除制定节点

C语言链表_第13张图片

C语言链表_第14张图片

1 STU* delete_link(STU *head, int num)
2 {
3  //判断链表是否存在
4  if(head == NULL)
5  {
6  printf("link not found\n");
7  return head;
8  }
9  else
10  {
11  STU *pb = head;//指向头节点
12  STU *pf = head‐>pre;//指向尾节点
13
14  //逐个节点寻找删除点
15  while((pb‐>num != num) && (pf‐>num != num) && (pf != pb))
16  {
17  pb = pb‐>next;//next方向移动
18  pf = pf‐>pre;//pre方向移动
19  if(pb‐>pre == pf)
20  break;
21  }
22
23  if(pb‐>num == num)//删除pb指向的节点
24  {
25
26  if(pb == head)//删除头节点
27  {
28  if(head == head‐>next)//链表只有一个节点
29  {
30  free(pb);
31  head = NULL;
32  }
33  else
34  {
35  head‐>next‐>pre = head‐>pre;
36  head‐>pre‐>next = head‐>next;
37  head = head‐>next;
38  free(pb);
39  }
40
41  }
42  else//删除中尾部节点
43  {
44  pb‐>pre‐>next = pb‐>next;
45  pb‐>next‐>pre = pb‐>pre;
46  free(pb);
47  }
48  }
49  else if(pf‐>num == num)//删除pf指向的节点
50  {
51
52  if(pf == head)//删除头节点
53  {
54  if(head == head‐>next)//链表只有一个节点
55  {
56  free(pf);
57  head = NULL;
58  }
59  else
60  {
61  head‐>next‐>pre = head‐>pre;
62  head‐>pre‐>next = head‐>next;
63  head = head‐>next;
64  free(pf);
65  }
66  }
67  else//删除中尾部节点
68  {
69  pf‐>pre‐>next = pf‐>next;
70  pf‐>next‐>pre = pf‐>pre;
71  free(pf);
72  }
73  }
74  else
75  {
76  printf("未找到%d相关的节点信息",num);
77  }
78  }
79
80  return head;
81 }

释放这个链表节点

1 STU* free_link(STU *head)
2 {
3  if(head == NULL)//链表为空
4  {
5  printf("link not found\n");
6  return NULL;
7  }
8  else//链表存在
9  {
10  STU *pb = head;
11  STU *tmp;
12  do
13  {
14  tmp = pb;
15  pb = pb‐>next;
16  free(tmp);
17  }while(pb != head);
18  }
19
20  return NULL;
21 }

你可能感兴趣的:(c语言,链表,开发语言)