每一個節點包括一個數據域一個指針域,節點在內存中地址能夠不連續,可是節點內部地址必然連續。
node
typedef struct Lnode{ int data; struct Lnode *next; }Lnode,*LinkList;
1)頭插法
算法
//頭插法創建帶頭結點的單鏈表 LinkList create1(LinkList &L){ Lnode *s; int x; L=(LinkList) malloc( sizeof(Lnode));//建立頭結點 L->next = NULL; //初始化 printf("往鏈表中添加數據,99999結束\n"); scanf("%",&x); while(x!=99999){ s = (Lnode*)malloc(sizeof(Lnode));//建立新節點 s->data = x; s->next = L->next; L->next = s; scanf("%d",&x); } return L; }
2)尾插法
函數
//尾插法創建單鏈表 LinkList create2(LinkList &L){ int x; L=(LinkList) malloc( sizeof(Lnode));//建立尾結點 Lnode *s,*r = L;//S爲插入節點指針,r爲尾指針 printf("往鏈表中添加數據,99999結束\n"); //scanf("%",&x); while(x!=99999){ s = (Lnode*)malloc(sizeof(Lnode));//建立新節點 scanf("%d",&x); s->data = x; r->next = s; r = s; //r指向新的表尾 } r->next = NULL;//尾節點指針置空 return L; }
1)按值查找spa
//按值查找表節點,返回節點位序,查找失敗返回-1 int locateElem(LinkList L, int e){ Lnode *P = L->next; int j=1; while (P!=NULL&&P->data!=e){ P = P->next; j++; } if(P->next == NULL && P->data == e) return j; else if(P->next != NULL && P->data == e) return j; else return -1; } //按值查找表節點,返回節點指針,這是方便鏈表運算實現 Lnode *locateElem2(LinkList L, int e){ Lnode *P = L->next; while (P!=NULL&&P->data!=e){ P = P->next; } return P;//失敗則返回空指針 }
2)按序號查找指針
//按序號查找表節點,返回節點值 int getElem(LinkList L,int i){ int j = 1; Lnode *P = L->next; if(i==0) return 0;//若是i=0,則返回頭結點的值,但頭結點不存值故返回0 if(i<0) return -1;//錯誤序號則返回-1 while(P&&j<i)//P非空 { P= P->next; j++; } return P->data; } //按序號查找表節點,返回節點指針,這是方便鏈表運算實現 Lnode *getElem1(LinkList L, int i){ int j = 1; Lnode *P = L->next; if(i==0) return L;//若是i=0,則返回頭結點 if(i<0) return NULL;//錯誤序號則返回NULL while(P&&j<i)//P非空 { P= P->next; j++; } return P; }
int getLength(LinkList L){ int count = 0; while(L->next->next!=NULL)//此處指針因人而異,思想就是尾節點指針爲空結束循環 { L = L->next; count ++; } return count; }
//插入節點算法1(後插,前插通常不考慮) //指定位置插入節點 int insertElem1(LinkList L,int i,int e){ if (i<=1||i>getLength(L)) { return 0; } else { Lnode *s,*p; p = getElem1(L,i-1);//獲取插入位置前驅 s = (Lnode*)malloc(sizeof(Lnode));//建立新節點 s->data = e; s->next = p->next;//此句和下面那句代碼不可顛倒,單鏈表只可找到後繼,因此後繼指針不能被先覆蓋 p->next = s; return 1; } } //插入節點算法2 //只交換數據,不改變指針,在已知節點位置的基礎上這個是最優算法 int insertElem2(LinkList L,int i,int e){ int temp; if (i<=1||i>getLength(L)) { return 0; } else { Lnode *s,*p; p = getElem1(L,i);//獲取插入位置前驅 s = (Lnode*)malloc(sizeof(Lnode));//建立新節點 s->data = e; s->next = p->next; p ->next = s; temp = p->data;//這裏作個數據交換 p->data = s->data; s->data = temp; return 1; } }
#include <stdio.h> #include <stdlib.h>//malloc函數頭文件 //單鏈表定義 typedef struct Lnode{ int data; struct Lnode *next; }Lnode,*LinkList; //頭插法創建帶頭結點的單鏈表 LinkList create1(LinkList &L){ Lnode *s; int x; L=(LinkList) malloc( sizeof(Lnode));//建立頭結點 L->next = NULL; //初始化 printf("往鏈表中添加數據,99999結束\n"); scanf("%",&x); while(x!=99999){ s = (Lnode*)malloc(sizeof(Lnode));//建立新節點 s->data = x; s->next = L->next; L->next = s; scanf("%d",&x); } return L; } //尾插法創建單鏈表 LinkList create2(LinkList &L){ int x; L=(LinkList) malloc( sizeof(Lnode));//建立尾結點 Lnode *s,*r = L;//S爲插入節點指針,r爲尾指針 printf("往鏈表中添加數據,99999結束\n"); //scanf("%",&x); while(x!=99999){ s = (Lnode*)malloc(sizeof(Lnode));//建立新節點 scanf("%d",&x); s->data = x; r->next = s; r = s; //r指向新的表尾 } r->next = NULL;//尾節點指針置空 return L; } //求單鏈表表長 int getLength(LinkList L){ int count = 0; while(L->next->next!=NULL) { L = L->next; count ++; } return count; } //按序號查找表節點,返回節點值 int getElem(LinkList L,int i){ int j = 1; Lnode *P = L->next; if(i==0) return 0;//若是i=0,則返回頭結點的值,但頭結點不存值故返回0 if(i<0) return -1;//錯誤序號則返回-1 while(P&&j<i)//P非空 { P= P->next; j++; } return P->data; } //按序號查找表節點,返回節點指針,這是方便鏈表運算實現 Lnode *getElem1(LinkList L, int i){ int j = 1; Lnode *P = L->next; if(i==0) return L;//若是i=0,則返回頭結點 if(i<0) return NULL;//錯誤序號則返回NULL while(P&&j<i)//P非空 { P= P->next; j++; } return P; } //按值查找表節點,返回節點位序,查找失敗返回-1 int locateElem(LinkList L, int e){ Lnode *P = L->next; int j=1; while (P!=NULL&&P->data!=e){ P = P->next; j++; } if(P->next == NULL && P->data == e) return j; else if(P->next != NULL && P->data == e) return j; else return -1; } //按值查找表節點,返回節點指針,這是方便鏈表運算實現 Lnode *locateElem2(LinkList L, int e){ Lnode *P = L->next; while (P!=NULL&&P->data!=e){ P = P->next; } return P;//失敗則返回空指針 } //插入節點算法1(後插,前插通常不考慮) //指定位置插入節點 int insertElem1(LinkList L,int i,int e){ if (i<=1||i>getLength(L)) { return 0; } else { Lnode *s,*p; p = getElem1(L,i-1);//獲取插入位置前驅 s = (Lnode*)malloc(sizeof(Lnode));//建立新節點 s->data = e; s->next = p->next;//此句和下面那句代碼不可顛倒,單鏈表只可找到後繼,因此後繼指針不能被先覆蓋 p->next = s; return 1; } } //插入節點算法2 //只交換數據,不改變指針,在已知節點位置的基礎上這個是最優算法 int insertElem2(LinkList L,int i,int e){ int temp; if (i<=1||i>getLength(L)) { return 0; } else { Lnode *s,*p; p = getElem1(L,i);//獲取插入位置前驅 s = (Lnode*)malloc(sizeof(Lnode));//建立新節點 s->data = e; s->next = p->next; p ->next = s; temp = p->data;//這裏作個數據交換 p->data = s->data; s->data = temp; return 1; } } int main(){ LinkList L,L1; /* create1(L); LinkList temp = L->next; while(temp->next != NULL) { printf("%d ", temp->data); temp = temp->next; } printf("頭插法與存數據的順序相反\n"); */ create2(L1); LinkList temp2 = L1->next; while(temp2 ->next != NULL) { printf("%d ", temp2->data); temp2 = temp2->next; } printf("尾插法與存數據的順序相同\n"); int length; length = getLength(L1); printf("單鏈表長度爲:%d\n",length); /* printf("輸入取值位序\n"); int i; scanf("%d",&i); printf("第%d位值爲%d\n",i, getElem(L1,i)); printf("輸入查找值\n"); int e; scanf("%d",&e); printf("值爲:%d位序爲:%d\n",e, locateElem(L1,e)); */ //插入節點算法1 /* int x1,x2; printf("插入節點算法1\n"); printf("插入位置:"); scanf("%d",&x1); printf("插入值:"); scanf("%d",&x2); int desert = insertElem1(L1,x1,x2); if(desert == 1) { printf("插入成功\n"); LinkList temp3 = L1->next; } else { printf("插入失敗,位置不合法\n"); } printf("打印鏈表(插入算法1)\n"); LinkList temp3 = L1->next; while(temp3 ->next != NULL) { printf("%d ", temp3->data); temp3 = temp3->next; } */ //插入節點算法2 int x3,x4; printf("插入節點算法2\n"); printf("插入位置:"); scanf("%d",&x3); printf("插入值:"); scanf("%d",&x4); int desert1 = insertElem2(L1,x3,x4); if(desert1 == 1) { printf("插入成功\n"); LinkList temp4 = L1->next; } else { printf("插入失敗,位置不合法\n"); } printf("打印鏈表(插入算法2)\n"); LinkList temp4 = L1->next; while(temp4 ->next != NULL) { printf("%d ", temp4->data); temp4 = temp4->next; } return 0; }
單鏈表做爲鏈表中最簡單的一種,擺脫了順序表對空間的束縛,能夠很好的支持動態操做。可是其問題也很明顯,每一個節點只能找到其直接後繼,而找不到其前一節點。在查找時須要從表頭開始遍歷表,會增長時間複雜度。code