線性結構四 鏈式存儲

連接方式存儲的線性表簡稱爲鏈表 Link Listnode

鏈表的具體存儲表示爲:c++

1)用一組任意的存儲單元來存放算法

2)鏈表中結點的邏輯次序和物理次序不必定相同。還必須存儲指示其後繼結點的地址信息spa

用一組地址任意的存儲單元存放線性表中的數據元素3d

鏈表是:線性表中數據爲(1,3,5,7.8)指針

 

 

單鏈表:data域:存放結點的數據域code

      next域:存放結點的直接後繼的地址(位置)的指針域blog

全部結點經過指針連接而組成單鏈表it

NULL:成爲空指針io

head: 頭指針,存放鏈表的第一個結點地址(每一個鏈表都須要有一個頭指針)

 

 

 

 單鏈表的通常圖示法:

 

單鏈表特色:

起始節點又叫作首結點,沒有前驅,故設頭指針head指向開始結點

鏈表由頭指針惟一肯定,單鏈表能夠用頭指針的名字來命名。頭指針是head的鏈表能夠稱爲表head

終端結點又稱尾結點,沒有後繼結點,因此終端結點的指針域爲空,NULL

除頭結點以外的結點爲表結點

爲運算操做方便,頭節點中不存數據哦~

 單鏈表的類型定義:

1 ytpedef struct node{
2 Datatype data; //數據域
3 struct node*next;//指針域,存放該結點的直接後繼結點的地址
4 } Node, *LinkList;

1.初始化

每個新建的單鏈表都須要進行一個初始化,(一個空的單鏈表是一個頭指針和一個頭結點構成的)

//創建一個空鏈表
LinkList InitiateLinkList(){
LinkList head;  //頭指針
head =malloc (sizeof(node)); //動態構建一節點,它是頭結點
head->next=null;
return head;

如今我們已經建立了一個新鏈表,接下來建立幾個數據域後如何來算表的長度呢?

:在單鏈表存儲結構中,線性表的長度等於單鏈表所含結點的個數(不含頭結點)

 

1 //求表長
2 int lengthLinklist (LinkList head){
3 Node *p;
4 p=head;j=0;
5 while(p->next!=null){//p的下一個指針不爲空繼續循環,當p的指針爲空跳出循環
6 p=p->next;//p指向下個結點
7 j++;長度加1
8 }
9 return (j);}

3.讀表元素

 

步驟;查找第I個結點

1.零計數器J爲0

2.令P指向頭節點

3.當下一個結點不空時,而且j<i時,j加1,p指向下一個結點

4.若是j等於i,則p所指結點爲要找的第i結點,不然,鏈表中無第i結點

 

 1 Node *GetlinkList(LinkList head,int i){
 2 Node *p;
 3 p=head->next;
 4 int c=1;
 5 while((c<i)&&(p!=NULL)){
 6 p=p->next;
 7 c++;
 8 }
 9 if(i==c)
10 return (p);
11 else return NULL;}

4.定位

定位運算是對給定表元素的值,找出這個元素的位置。對
於單鏈表,給定一個結點的值,找出這個結點是單鏈表的
第幾個結點。定位運算又稱爲按值查找。
具體步驟:
一、令p指向頭結點
二、令i=0
三、當下一個結點不空時, p指向下一個結點,同時i的值加1
四、直到p指向的結點的值爲x,返回i+1的值。
五、若是找不到結點值爲x的話,返回值爲0

 1 int LocateLinklist (LinkList head ,Data Type x){
 2 //求表head中第一個值等於x的結點的序號,若不存在這種結點,返回結果爲0
 3 Node *p=head;//p是工做指針
 4 p=p->next;//初始時P指向首結點
 5 int i=0;//i表明 結點的序號,這裏初值爲
 6 while(p!=null&&p->data!=x){//訪問鏈表
 7 i++;
 8 p=p->next;
 9 }
10 if(p!=null)
11 return i+1;
12 else return 0;}

5.插入

插入運算是將值爲x的新結點插入到表的第i個結點
的位置上,即插入到ai-1與ai之間。
具體步驟:
(1)找到ai-1存儲位置p
(2)生成一個數據域爲x的新結點*s
(3)令結點*p的指針域指向新結點
(4)新結點的指針域指向結點ai

 

 

 1 void InsertLinklist (LinkList head, DataType x, int i)
 2 //在表head的第i個數據元素結點以前插入一個以x爲值的新結點
 3 {
 4 Node *p,*q;
 5 if (i==1) q=head;
 6 else q=GetLinklist (head, i-1); //找第 i-1個數據元素結點
 7 if (q==NULL) //第i-1個結點不存在
 8 exit(「找不到插入的位置」);
 9 else
10 {
11 p=malloc(sizeof (Node) );p->data=x; //生成新結點
12 p->next=q->next; //新結點鏈域指向*q的後繼結點
13 q->next=p; //修改*q的鏈域
14 }
15 }

6. 刪除

算法步驟
刪除運算是將表的第i個結點刪去。
(1)找到ai-1的存儲位置p
(2)令p->next指向ai的直接後繼結點
(3)釋放結點ai的空間,將其歸還給"存儲池"。

 1 void DeleteLinklist(LinkList head, int i)
 2 //刪除表head的第i個結點
 3 {
 4 Node *q;
 5 if(i==1) q=head;
 6 else q=GetLinklist(head, i-1); //先找待刪結點的直接前驅
 7 if(q !== NULL && q->next != NULL) //若直接前驅存在且待刪結點存在
 8 {
 9 p=q->next; //p指向待刪結點
10 q->next=p->next; //移出待刪結點
11 free(p); //釋放已移出結點p的空間
12 }
13 else exit (「找不到要刪除的結點」); //結點不存在
14 }

 

雙向循環鏈表

 

在鏈表中設置兩個指針域,
一個指向後繼結點
一個指向前驅結點
這樣的鏈表叫作雙向鏈表

 

 雙向鏈表的結構體

雙向循環鏈表適合應用在須要常常
查找結點的前驅和後繼的場合。 找
前驅和後繼的複雜度均爲: O(1)

 

 

1 struct dbnode
2 { DataType data;
3 struct dbnode *prior, *next;
4 };
5 typedef struct dbnode *dbpointer;
6 typedef dbpointer Dlinklist;
7 假設雙向鏈表中p指向某節點
8 則有 p->prior->next 與p->next->prior相等

雙向鏈表中結點的刪除

p指向待刪結點, 刪除*p可經過下述語句完成:

1 (1)p->prior->next=p->next; //p前驅結點的後鏈指向p的後繼結點
2 (2)p->next->prior=p->prior; //p後繼結點的前鏈指向p的前驅結點
3 (3)free(p); //釋放*p的空間

1) 、 (2) 這兩個語句的執行順序能夠顛倒。

 

 雙向鏈表中結點的插入

p所指結點的後面插入一個新結點*t, 須要修改四個指針:
(1)t->prior=p;(2)t->next=p->next;(3)p->next->prior=t;(4)p->next=t;

相關文章
相關標籤/搜索