1.新建
算法:使p1指向新开辟的结点,p2指向链表中最后一个结点,把p1所指的结点连接在p2所指结点的后面,用“p2->next=p1”来实现。
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<malloc.h>
4
5 #define LEN sizeof(struct student)
6
7 struct student{
8 long num;
9 float score;
10 struct student *next;
11 };
12
13 struct student *creat(void){
14 struct student *head=NULL,*p1,*p2;
15 int n=0;
16
17 p1=(struct student *)malloc(LEN);
18 p2=p1;
19
20 printf("Input one student's data:
");
21 scanf("%ld,%f",&p1->num,&p1->score);
22 while(p1->num!=0)
23 {
24 n++;
25 if(n==1)
26 head=p1;
27 else
28 p2->next=p1;
29 p2=p1;
30 p1=(struct student *)malloc(LEN);
31 printf("Input one student's data:
");
32 scanf("%ld,%f",&p1->num,&p1->score);
33 }
34 p2->next=NULL;
35 return head;
36 }
2.输出
1 void print(struct student *head)
2 {
3 struct student *p;
4 for(p=head;p!=NULL;p=p->next)
5 {
6 printf("%ld,%f
",p->num,p->score);
7 }
8 }
3.删除
这是我用for循环编写的:
1 struct student *del(struct student *head,long num){
2 struct student *p1,*p2;
3 if(head==NULL)
4 printf("The list is NULL.
");
5 else
6 for(p1=head;p1!=NULL;p1=p1->next)
7 {
8 if(p1->num==num)
9 {
10 if(p1==head)
11 head=p1->next;
12 else
13 p2->next=p1->next;
14 break;
15 }
16 else
17 {
18 p2=p1;
19 }
20 }
21
22 if(p1==NULL)
23 printf("cannot find the %ld.
",num);
24 return head;
25 }
书上用while循环编写的:
1 struct student *del(struct student *head,long num){
2 struct student *p1,*p2;
3 if(head==NULL)
4 {
5 printf("The list is NULL.
");
6 return head;
7 }
8 p1=head;
9 while(p1->num!=num&&p1->next!=NULL)//当前结点不是要删除的结点而且后面还有结点。
10 {
11 p2=p1;
12 p1=p1->next;
13 }
14 if(p1->num==num)
15 {
16 if(p1==head)
17 head=p1->next;
18 else
19 p2->next=p1->next;
20 }
21 else
22 printf("%ld cannot be found.
",num);
23 return head;
24 }
4.插入
使用for循环编写:
1 struct student *insert(struct student *head,struct student *stu){
2 struct student *p0,*p1,*p2;
3 p0=stu;
4 for(p1=head;p1!=NULL;p1=p1->next)
5 {
6 if(p1->num < p0->num)
7 p2=p1;
8 else
9 {
10 if(p1==head)
11 head=p0;
12 else
13 p2->next=p0;
14 p0->next=p1;
15 break;
16 }
17 }
18 if(p1==NULL)
19 {
20 if(p1==head)
21 head=p0;
22 else
23 p2->next=p0;
24 p0->next=NULL;
25 }
26 return head;
27 }
使用while循环编写:
1 struct student *insert(struct student *head,struct student *stu){
2 struct student *p0,*p1,*p2;
3 p0=stu;
4 if(head==NULL)
5 {
6 head=p0;
7 p0->next=NULL;
8 }
9 else
10 {
11 p1=head;
12 while(p1->num<p0->num&&p1->next!=NULL)
13 {
14 p2=p1;
15 p1=p1->next;
16 }
17 if(p1->num>p0->num)
18 {
19 if(p1==head)
20 head=p0;
21 else
22 p2->next=p0;
23 p0->next=p1;
24 }
25 else
26 {
27 p1->next=p0;
28 p0->next=NULL;
29 }
30 }
31 return head;
32 }
我刚开始用的函数原型是:
struct student *insert(struct student *head)
插入的结点在函数内部产生,事实证明这样做是不行的。因为插入的结点数据在函数调用完之后就释放了,没有保存。
后来函数原型改为:
struct student *insert(struct student *head,struct student stu)
插入的结点在主函数内产生,经过一番试验后,发现也不对。新结点的数据传递给形参stu,形参stu有自己的地址,insert函数把形参stu连接在了链表中,函数调用完之后,形参stu的值就释放了,链表中新结点处的值为不确定的值。
链表学习心得:在对链表进行操作的过程中,要设两个循环变量指针:p1和p2。其中p1指向当前要进行操作或处理的结点,p2指向当前结点的前一个结点,当前结点的后一个结点可以直接用p1->next表示。循环遍历数组的话,可以用p++和p--指向后一个元素和前一个元素,但是因为链表中的结点不是连续存放的,所以只能用设两个循环变量的方法遍历数组。