单向链表操作:新建,输出,删除,插入

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 }
删除结点1

书上用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 }
删除结点2

 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 }
插入结点1

使用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 }
插入结点2

我刚开始用的函数原型是:

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--指向后一个元素和前一个元素,但是因为链表中的结点不是连续存放的,所以只能用设两个循环变量的方法遍历数组。

原文地址:https://www.cnblogs.com/Camilo/p/3384498.html