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

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

你可能感兴趣的:(链表)