C语言:随笔9--链表
接上篇:https://blog.csdn.net/m0_37957160/article/details/108685364
例子:寫一函數(shù)以刪除動態(tài)鏈表中指定的結點。
解題思路:
1、從p指向的第一個結點開始,檢查該結點中的num值是否等于輸入的要求刪除的那個學號。
2、如果相等就將該結點刪除,如不相等,就將p后移一個結點(繼續(xù)尋找 ),再如此下去,直到遇到表尾為止。
3、可以設兩個指針變量p1和p2,先使p1指向第一個結點。
4、如果要刪除的不是第一個結點,則使p1后移指向下一個結點(將p1->next賦給p1),在此之前將p1的值賦給p2,使p2指向剛才檢查過的那個結點(為什么要這樣呢?因為剛才的那個圖我們知道我們要實現(xiàn)刪除操作C,必須這個結點B的next指向后一個結點D的地址,所以這個p2還是必須要先指向B保留一下,之后p2的next才能指向p1)。
算法流程圖:
代碼如下:(先創(chuàng)建鏈表在刪除結點)
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#define LEM sizeof(struct student)//student結構大小
struct student *create();//創(chuàng)建鏈表
struct student *del(struct student *head,int num);//del函數(shù)用于刪除結點,*head即鏈表的頭指針,num是要刪除的結點num
void print(struct student *head);//打印鏈表
struct student
{int num;float score;struct student *next};
int n;//全局變量,用來記錄存放了多少數(shù)據(jù)void main()
{struct student *stu,*p;int n;stu=creat();p=stu;print(p);printf("Please enter the num to delete:");scanf("%d",&n);print(del(p,n));printf("\n\n");system("pause");
}struct student *creat()
{struct student *head;struct student *p1, *p2;p1 = p2 = (struct student *)malloc(LEN); // LEN是student結構的大小printf("Please enter the num :");scanf("%d", &p1->num);printf("Please enter the score :");scanf("%f", &p1->score);head = NULL; n = 0; while( p1->num ){n++;if( 1 == n ){head = p1; }else{p2->next = p1;}p2 = p1;p1 = (struct student *)malloc(LEN);printf("\nPlease enter the num :");scanf("%d", &p1->num);printf("Please enter the score :");scanf("%f", &p1->score);}p2->next = NULL;return head;
}void print(struct student *head)
{struct student *p;printf("\nThere are %d records!\n\n", n);p = head;if( head ){do{printf("學號為 %d 的成績是: %f\n", p->num, p->score);p = p->next;}while( p );}
}struct student *del(struct student *head,int num)//1指向struct student結構的指針
{struct student *p1,*p2;//2指向結構的指針if(NULL==head)//3我們要判斷上邊函數(shù)傳進來的指向頭結點的這個指針是否為NULL,如果頭結點指向NULL,這是一個空鏈表{printf("\nThis list is null!\n");goto end;//4直接跳轉到end這個地方}p1=head;//p1指向headwhile(p1->num!=num&&p1->next!=NULL)//5p1指向鏈表的第一個結點,這個結點的學號不等于我們要刪除的學號的時候;p1的next還不指向NULL,也就是p1還不是最后一個結點的時候(&&操作兩個只要一個為0,則就為0){p2=p1;//6p1的值就給了p2p1=p1->next;//7p1就指向了下一個數(shù)據(jù)(下一個結點)(這個時候第一個數(shù)據(jù)是p2指向了,第二個數(shù)據(jù)是p1指向了)}//直到不滿足上述while的兩個條件才會退出循環(huán)if(num==p1->num)//8p1指向的學號p1->num,等于我們要刪除的學號num的時候就應該要做刪除操作了{if(p1==head)//8還需要再驗證一下p1這個時候是不是頭結點{head=p1->next;//是的話,就必須把頭結點給p1的下一個,然后才把p1給刪了,(你不能直接把頭給切了,如果把頭給切了拿什么來返回)(頭應該指向p1的下一任,然后才能把頭給切掉)}else//如果不是頭結點,(p2是指向了p1的上一任){p2->next=p1->next;//把p1的next賦值給p1的next(比如p2是指向A結點,P1是結點,p1的next是C結點,因為p1的next就是B指向C(B->C),p2的next就是A指向B(A->B),就是將C給了A,就是直接把B給刪除掉了(A->C))(next是一個指針,指向下一個地點的指針)}printf("\nDelete No:%d succeed!\n",num);n=n-1;//n是作為一個全局變量用來記錄鏈表的數(shù)據(jù)數(shù)}else{printf("%d not been found!\n",num)}
end://直接結束,因為空鏈表沒有辦法刪除return head;}
結果:
? ? ?
鏈表的插入:
?對鏈表的插入是指將一個結點插入到一個已有的鏈表中。
為了做到正確插入,必須解決兩個問題:
(1)怎樣找到插入位置;
(2)怎樣實現(xiàn)插入。
我們可以先用指針變量p0指向待插入的結點,p1指向第一個結點。將p0->num于p1->num相比較,如果p0->num大于p1->num,此時將p1后移,并使p2指向剛才p1所指的結點。 (大前提num在列表中都 是按照大小存放的)
(下邊abc是一種插入方法,02在01之后,03之前,所以插入位置肯定在03之前,找到插入位置,告訴這個鏈表我要進去,所以鏈表先把03給甩了,這時候p1就指向了03,p2->next還是指向03,之后開始脫節(jié)(p1在指向下一個位置之前,我們要用p2要保存一下p1原來的位置,p1才可以放心的走),將p2->next指向了02(p2),這時候p0->next指向了p1也就是我們的03,這樣就做好了交接工作,把他給鏈了進來。(這時候我們就看到了主要發(fā)生變化的就是他們的next指針,所以我們在鏈表中的第三個數(shù)據(jù)他的next變量非常重要,它記錄了下一個結點的位置,只要改變他的位置就可以成功的發(fā)生刪除和插入操作)(在中間比較麻煩,先斷開,第一個指向它p0,他再指向第三個)
d是一種插入方法,(就是插入的在最前面,就是在他的頭結點之前,那么我們的head就指向了它p0。他的next就指向了我們原來的第一個結點)
e是一種插入方法(要插入的位置剛好在最后的,要插入的在最后,那么必須使它的p0->next指向null)
?
流程圖:
首先p1指向head,p0指向我們要輸入的一個結構,如果鏈表是空表的話,head指向p0,p0->指向NULL。不是空表我們就來判斷
代碼:
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>#define LEM sizeof(struct student)//student結構的大小
struct student *create();//創(chuàng)建鏈表
struct student *del(struct student*head,int num); //del函數(shù)用于刪除結點, *head即鏈表的頭指針, num是要刪除的結點num。
struct student *insert(struct student *head,struct student *stu_2);// 第一個參數(shù)需要被插入的鏈表// 第二個參數(shù)待插入的結構的地址
void print(struct student *head);//打印鏈表struct student
{int num;float score;struct student *next;
};
int n;//全局變量,用來記錄存放了多少數(shù)據(jù)
void main()
{struct student *stu,*p,stu_2;int n;stu=creat();p=stu;print(p);printf("\nPlease input the num to delete:")scanf("%d",&n);print(del(p,n));printf("\nPlease input the num to insert:")scanf("%d",&stu_2.num);printf("Please input the score: ");scanf("%f", &stu_2.score);p = insert(stu, &stu_2);//用p指向了他返回的頭指針print( p );//把它給打印出來//其實也可以不用p直接嵌套調(diào)用print(insert(stu, &stu_2));printf("\n\n");system("pause");
}struct student *creat()
{struct student *head;struct student *p1, *p2;p1 = p2 = (struct student *)malloc(LEN); // LEN是student結構的大小printf("Please enter the num :");scanf("%d", &p1->num);printf("Please enter the score :");scanf("%f", &p1->score);head = NULL; n = 0; while( p1->num ){n++;if( 1 == n ){head = p1; }else{p2->next = p1;}p2 = p1;p1 = (struct student *)malloc(LEN);printf("\nPlease enter the num :");scanf("%d", &p1->num);printf("Please enter the score :");scanf("%f", &p1->score);}p2->next = NULL; return head;
}
//打印
void print(struct student *head)
{struct student *p;printf("\nThere are %d records!\n\n", n);p = head;if( head ){do{printf("學號為 %d 的成績是: %f\n", p->num, p->score);p = p->next;}while( p );}
}struct student *del( struct student *head, int num)
{struct student *p1, *p2;if( NULL == head ){printf("\nThis list is null!\n");goto end;}p1 = head;while( p1->num != num && p1->next != NULL){p2 = p1;p1 = p1->next;}if( num == p1->num ){if( p1 == head ){head = p1->next;}else{p2->next = p1->next;}printf("Delete No: %d succeed!\n", num);n = n-1;}else{printf("%d not been found!\n", num);}end:return head;
}
//插入
struct student *insert(struct student *head,struct student *stu_2)
{struct student *p0,*p1,*p2;p1=head;p0=stu_2;if(NULL==head){head=p0;p0->next=NULL;}else{while((p0->num > p1->num)&&(p1->next!=NULL))//意思就是待插入的102大于101,或者//兩種情況退出while((第一種p0->num < p1->num)達到了插入的條件,)(第二種p0跑到了最后表的結尾){p2=p1;//p2用來保存p1的結點(因為我們插入需要用到p1的上一個結點,所以用p2來保存)p1=p1->next;//p1跳槽指向下一個節(jié)點(其實這個while循環(huán)是在為中間插入做前期工作)}if(p0->num <= p1->num)//小于的話又有兩種情況:{if(head==p1)//p1是頭結點,插入頭部{head=p0;}else//普通情況,插入中間{p2->next=p0;//p2是剛才p1的上一個結點的值,p2的next指向了p0}p0->next=p1;//p0的next指向了p1 }else//p0的num最大,插入到末尾{p1->next=p0;p0->next=NULL}}n=n+1;//由于插入,所以增加了一位數(shù)據(jù)成員進入鏈表中。return head;//返回插入鏈表的頭指針(后再通過print調(diào)用)
}
//還可以改寫,需要多次插入
最后實現(xiàn)插入程序并制作一個學生成家管理系統(tǒng)。
總結
以上是生活随笔為你收集整理的C语言:随笔9--链表的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言:随笔8--结构体
- 下一篇: C语言:随笔10--共用体