連接方式存儲的線性表簡稱爲鏈表 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;