單鏈表整表的創建
單鏈表整表創建的思路:
- 聲明一個結點p和計數器變量i;
- 初始化一個空鏈表L;
- 讓L的頭結點的指針指向NULL,即建立一個帶頭結點的單鏈表;
- 循環:
生成一新結點賦值給p;
隨機生成一數字賦值給p指針的數據域p->data=rand();
將p結點插入到頭結點與前一新結點之間。
實現代碼如下:
/*隨機產生n個元素的值,建立帶頭結點的單鏈表L(頭插法)*/
void CreatListHead(LinkList *L,int n)
{
LinkList p;
int i;
srand(time(0)); /*初始化隨機數種子*/
*L=(LinkList)malloc(sizeof(Node));
(*L)->next=NULL; /*先建立一個帶頭結點的單鏈表*/
for(i=0;i<n;i++)
{
p=(LinkList)mallloc(sizeof(Node)); /*生成新結點*/
p->data=rand()%100+1;
p->next=(*L)->next;
(*L)->next=p; /*插入到表頭*/
}
}
這段代碼裏,我們其實用的是插隊的方法,始終讓新結點在第一的位置,簡稱爲頭插法。同樣也有尾插法實現整表的創建。
具體實現代碼如下:
/*隨機產生n個元素的值,建立帶頭結點的單鏈表L(尾插法)*/
void CreateListTail(Linklist *L,int n)
{
LinkList p,r;
int i;
srand(time(0)); /*初始化隨機數種子*/
*L=(LinkList)malloc(sizeof(Node)); /*爲整個單鏈表*/
r=*L; /*r爲指向尾部的結點*/
for(i=0;i<n;i++)
{
p=(LinkList)mallloc(sizeof(Node)); /*生成新結點*/
p->data=rand()%100+1;
r->next=p;/*將尾部終端結點的指針指向新結點*/
r=p; /*將當前的新結點定義爲表尾終端結點*/
}
r->next=NULL;
}
注意L與r的關係,L是指整個單鏈表,而r是指向結點的變量,r會隨着循環不斷地變化結點,而L則是隨着循環增長爲一個多結點的鏈表。
單鏈表整表的刪除
單鏈表整表刪除的思路如下:
- 聲明一結點p和q;
- 將第一個結點賦值給p;
- 循環:
將下一結點賦值給q;
釋放p;
將q賦值給p。
實現代碼算法如下:
/*初始條件:順序線性表L已存在,操作結果:將L重置爲空表*/
Status CLearList(LinkList *L)
{
LinkList p,q;
p=(*L)->next;
while(p) /*沒到表尾*/
{
q=p->next;
free(p);
p=q;
}
(*L)->next=NULL; /*頭結點指針域爲空*/
return OK;
}
單鏈表結構與順序存儲結構優缺點
存儲分配方式
- 順序存儲結構用一段連續的存儲單元依次存儲線性表的數據元素
- 單鏈表採用鏈式存儲結構,用一組任意的存儲單元存放線性表的元素
時間性能
查找
順序存儲結構O(1)
單鏈表O(n)插入和刪除
順序存儲結構需要平均移動表長一半的元素,時間爲O(n)
單鏈表在線出某位置的指針後,插入和刪除時間僅爲O(1)
空間性能
- 順序存儲結構需要預分配存儲空間,分大了,浪費,分小了易發生上溢
- 單鏈表不需要分配存儲空間,只要有就可以分配,元素個數也不受限制