C語言——單向連結串列與增刪改查
阿新 • • 發佈:2021-01-17
文章目錄
認識連結串列
·連結串列是可以動態地按需進行儲存分配的一種結構。
·與陣列相比較連結串列更加靈活,陣列需要事先定義固定長度,而連結串列不需要。
·連結串列由資料域和指標域組成。資料域用來存放所需要的資料,指標域用來存放下一個結點的位置(地址)。
例子:建立一個關於學生資訊的結構體,把此結構體當作連結串列的結點。
struct student
{
char name[10];//姓名
int weight;//體重
int height; //身高
int sex;//性別
struct student* next;//用於存放下一結點的地址
};
形象點說就是每個結點都是一個島嶼,而你想去到下個島嶼時你得先知道下一個島嶼的位置。資料域是島上的內容,指標域是島上的路標,告訴你下一個島嶼的位置。
建立單向連結串列
單向連結串列的結構:
·頭指標是連結串列的入口。
·每個結點通過其本身的指標訪問下一個結點,因為其本身的指標存放著下一個結點的地址。
·頭指標可不存放資訊只記錄下一結點地址。
·羅列一下我們要怎麼建立一個連結串列。
- 為每個結點分配記憶體空間,建立一個結點。
- 記錄連結串列的入口。
- 連線前後兩個結點。
- 建立連結串列模組化
詳細操作如下:
struct student 這是連結串列結點的樣子
{
char name[10];//姓名
int weight;//體重
int height;//身高
int sex;//性別
struct student* next;//用於存放下一結點的地址
};
struct student* creatstu() 建立連結串列的函式
{
struct student* head=NULL;//用來記錄連結串列入口,建立完成後返回此指標
struct student* p1;//用來建立新結點
struct student* p2;//記錄p1前一個結點
int n = 0;//記錄是否需要把結點地址賦予頭指標
p1 = p2 = (struct student*)malloc(sizeof(struct student));//為結點分配記憶體
scanf("%s %d %d %d", p1->name,&p1->height, &p1->weight, &p1->sex);
while (p1->height != 0)//停止建立的條件可自行調整
{
n++;
if (n == 1)head = p1;//如果是第一個結點,他的地址要給到頭指標
else p2->next = p1;//如果不是便讓p2得到p1結點的位置並連線,這樣p1這個指標可以繼續開闢新結點
p2 = p1;//p2每次都走到p1結點,p1結點此時為最後結點
p1= (struct student*)malloc(sizeof(struct student));//分配一個新的記憶體空間給p1,開創新結點
scanf("%s %d %d %d",p1->name, &p1->height, &p1->weight, &p1->sex);
}
p2->next=NULL;//迴圈結束說明輸入結束,此時p2為最後一個結點
return head;//返回頭指標
}
連結串列建立完成後返回頭指標給呼叫該函式的函式,此時便可以通過訪問頭指標來訪問整個連結串列。
·尋找時與陣列的區別:連結串列的時間複雜度為O(n)(通過指標定址一個一個尋找),陣列為O(1)(知道下標直接訪問)。
連結串列的增刪改查
- 增
如何往已經建立好的連結串列中繼續加入結點呢?有兩種方法:頭插法為尾插法。
struct student* stu()//建立學生結點
{
struct student* p;
p = (struct student*)malloc(sizeof(struct student));
p->next = NULL;
return p;
}
頭插法:使頭指標指向新結點,新結點的指標指向原本第一個結點。
struct student* newstu=stu();//得到該新結點的地址
newstu->next=head->next;//先把新結點與原本的第一個結點連線
head->next=newstu;//再把頭指標與新結點連線
為什麼不能調轉順序?因為調轉後無法連線原來的舊結點
尾插法:找到最後一個結點並連線
struct student* newstu=stu();//得到該新結點的地址
struct student* search=head;//設定一個用於搜尋的指標
while(search->next!=NULL)search=search->next;//遍歷連結串列,當其退出迴圈時便找到了最後一個
search->next-newstu;//連線兩個結點
- 刪
刪除一個結點要先找到該節點,然後連線前後兩個結點。
struct student* search=head,follow=head;//設定一個用於搜尋的指標
while(search!=`````)//自行定義需刪除結點的資訊
{
follow=search;//記錄當前位置
search=search->next;//尋找新位置
}
找到後:
follow->next=search->next;//連線兩個結點
free(search)//釋放該記憶體空間
- 改
同樣設定一個用於搜尋的指標,找到需要修改的資訊即可。 - 查
設定用於搜尋的指標進行遍歷便可。
//只做一個粗略的介紹,具體的邊界情況請自行討論