04.線性表(三)鏈式儲存結構.單鏈表2,鏈式單鏈
鏈式儲存結構.單鏈表2
順序儲存結構的建立實質是一個數組的初始化,儲存空間連續且其大小和類型已經固定;單鏈表格儲存體空間不連續,是一種動態結構且它所佔用空間的大小和位置是不需要預先分配劃定的,可以根據系統的情況和實際的需求即時產生。一.單鏈表的整表建立 建立單鏈表的過程就是一個動態產生鏈表的過程,即從“空表”的初始化起,依次建立各元素結點,並逐個插入鏈表。1.演算法思路(1)聲明一個結點p和計數器變數i;(2)初始化一空鏈表L(3)讓鏈表L的頭結點的指標指向NULL,即建立一個帶頭結點的單鏈表 *L=(LinkList)malloc(sizeof(Node)); (*L)->next=NULL;(4)迴圈: a.產生一個新結點賦值給p; b.隨機產生一個數字賦值給p的資料域p->data; c.將p插入到頭結點之前與一新結點之間2.源碼實現(1)頭插法:始終讓新結點在第一的位置/*隨機產生n個元素的值,建立帶頭結點的單鏈線性表L(頭插法)*/typedef struct Node *LinkList; //定義LinkListvoid CreateListHead(LinkList *L,int n){ LinkList p; int i; srand(time(0)); //初始化隨機數種子 /*1.建立一個帶頭結點的單鏈表*/ *L=(LinkList)malloc(sizeof(Node)); //初始化一空鏈表L (*L)->next=NULL; //讓鏈表L的頭結點的指標指向NULL /*2.迴圈插入新結點到單鏈表中*/ for(i=0;i<n;i++) { p=(LinkList)malloc(sizeof(Node)); //產生一個新結點 p->data=rand()%100+1; //設定新結點的資料域 p->next=(*L)->next; //設定新結點的指標域:使p結點的後繼結點為頭指標之前指向的結點 (*L)->next=p; //更改頭結點的後繼結點為新結點p } }(2)後插法:把每次新結點都插在終端結點的後面/*隨機產生n個元素的值,建立帶頭結點的單鏈線性表L(尾插法)*/typedef struct Node *LinkList; //定義LinkListvoid CreateListTail(LinkList *L,int n){ LinkList p,r; int i; srand(time(0)); //初始化隨機數種子 /*1.建立一個帶頭結點的單鏈表並設定尾結點*/ *L=(LinkList)malloc(sizeof(Node)); //初始化一空鏈表L,L指整個單鏈表 r=*L; //r為指向尾部的結點 /*2.迴圈插入新結點到單鏈表中*/ for(i=0;i<n;i++) { p=(LinkList)malloc(sizeof(Node)); //產生一個新結點 p->data=rand()%100+1; //設定新結點的資料域 r->next=p; //將表尾終端結點的指標指向新結點 r=p; //將當前的新結點定義為表尾終端結點 } r->next=NULL; //此時的尾結點為p,相當於p->next=null,,表示當前鏈表結束}注釋:注意L與r的關係,L是指整個單鏈表,而r是指向尾結點的變數;r會隨著迴圈不斷地變化結點,而L則是隨著迴圈增長為一個多結點的鏈表。
升華筆記:1.如何建立一個帶頭結點的單鏈表?(1)初始化一空鏈表L(2)讓鏈表L的頭結點的指標指向NULL 源碼實現: LinkList *L; *L=(LinkList)malloc(sizeof(Node)); (*L)->next=NULL; 2.頭插法如何?插入新結點?(1)產生一個新結點(2)設定新結點的資料域(3)設定新結點的指標域(4)將新結點作為上一個結點的後繼結點 源碼實現:p=(LinkList)malloc(sizeof(Node)); p->data=e; //e為資料 p->next=(*L)->next; //設定新結點的指標域:使p結點的後繼結點為頭指標之前指向的結點 (*L)->next=p; //更改頭結點的後繼結點為新結點p3.尾差法如何?插入新結點?(1)聲明一個結點r,並將其設定為鏈表L的尾部結點(2)產生一個新結點p(3)設定新結點的資料域(4)將表尾終端結點的指標指向新結點,並將新結點設定為尾部結點(5)設定新的表位結點指標指向NULL,表示當前鏈表結束 源碼實現:LinkList *L,p; *L=(LinkList)malloc(sizeof(Node)); r=*L; p=(LinkList)malloc(sizeof(Node)); p->data=rand()%100+1; r->next=p; r=p; 二.單鏈表的整表刪除
1.演算法思路
(1)聲明一個結點p和q;(2)將單鏈表的第一個結點賦值給p(3)迴圈: a.將下一結點賦值給q b.釋放p c.將q賦值給p
2.源碼實現:/*初始化條件:單鏈式線性表L已存在,操作結果:將單鏈表L重設為空白表*/typedef struct Node *LinkList; //定義LinkList
typedef int Status;
Status ClearList(LinkList *L){ LinkList p,q; p=(*L)->next; //將單鏈表的第一個結點賦值給結點p while(p) { q=p->next; //將p的下一個結點設定為q free(p); //釋放結點p p=q; //p指向下一結點q } (*L)->next=NULL; //最後,單鏈表頭結點指標域為空白 returm OK;}
三.單鏈表結構與順序儲存結構的優缺點
1.儲存分配方式(1)順序儲存結構用一段聯絡的儲存單元依次儲存線性表的資料元素(2)單鏈表採用鏈式儲存結構,用一組任意的儲存單元存放線性表的元素
2.時間效能(1)尋找:順序儲存結構O(1);單鏈表O(n)(2)刪除和插入:順序儲存結構需要平均移動表長一半的元素,時間為O(n);單鏈表在指出某位置的指標後,插入和刪除時間僅為O(1)
3.空間效能(1)順序儲存結構需要預分配儲存空間,分大了,浪費,分小了易發生溢出;(2)單鏈表不需要分配儲存空間,只要有就可以分配,元素個數不受限制