線性表的單鏈表儲存學習
阿新 • • 發佈:2019-01-31
線性表:單鏈表儲存
單鏈表由結點構成,每個結點包括一個數據域和一個指示其直接後繼位置的指標域。連結串列中第一個結點的儲存位置叫做頭指標。在單鏈表中可以有頭結點,也可以沒有,但是一定有頭指標。一般,有頭結點的方式處理會比較簡單明瞭。以下程式是針對有頭結點的情況。頭結點的資料域可以不儲存任何資訊,頭結點的指標域儲存指向第一個結點的指標。最後一個結點的指標域指向空NULL。
/*線性錶鏈式儲存的相應程式碼: 1.線性表的順序單鏈表儲存結構程式碼 2.初始順序單鏈表 3.讀取順序單鏈表元素操作 4.插入操作 5.刪除操作 6.判斷線性表是否為空 7.順序單鏈表整表建立:頭插法 8.順序單鏈表整表建立:尾插法 9.順序單鏈表整表刪除 10.遍歷順序單鏈表 11.順序單鏈表長度 */ #include<stdio.h> #include<stdlib.h> #include<time.h> #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 #define MAXSIZE 20 /* 儲存空間初始分配量 */ typedef int Status;/* Status是函式的型別,其值是函式結果狀態程式碼,如OK等 */ typedef int ElemType;/* ElemType型別根據實際情況而定,這裡假設為int */ /* 1.線性表的順序單鏈表儲存結構程式碼 */ typedef struct Node { ElemType data; struct Node *next; }Node; typedef struct Node *LinkList; /* 定義LinkList */ /* 2.初始順序單鏈表 */ Status InitList(LinkList *L) { *L = (LinkList)malloc(sizeof(Node)); /* 產生頭結點,並使L指向此頭結點 */ if(!(*L)) /* 儲存分配失敗 */ return ERROR; (*L)->next = NULL; /* 指標域為空 */ return OK; } /* 3.讀取順序單鏈表元素操作 */ /* 宣告一個指標p指向連結串列的第一個結點,初始化j從1開始; 當 j<i 時,就遍歷連結串列,讓p的指標向後移動,不斷指向下一個結點,j累加1; 若到連結串列末端p為空,則說明第i個節點不存在; 否則查詢成功,返回結點p的資料 */ Status GetElem(LinkList L,int i,ElemType *e) { int j; LinkList p; p = L->next; /* L是頭指標,指標p指向連結串列的第一個結點 */ j = 1; while ( p && j < i) { p = p->next; ++j; } if( !p || j>i ) /*讀取的位置為空,或者i=0 */ return ERROR; *e = p->data; return OK; } /* 4.順序單鏈表插入操作 */ /* 宣告一個指標p指向連結串列的頭結點,初始化j從1開始; 當 j<i 時,就遍歷連結串列,讓p的指標向後移動,不斷指向下一個結點,j累加1; 若到連結串列末端p為空,則說明第i個節點不存在; 否則查詢成功,在系統中生成一個空結點s; 將資料元素e賦給s->data; 單鏈表的插入標準語句s->next = p->next; p->next = s; 返回成功。 */ Status ListInsert(LinkList *L,int i,ElemType e) { int j; LinkList p,s; p = *L; j = 1; while( p && j < i) /*尋找第i-1個結點,不能為空 */ { p = p->next; ++j; } if( !p || j> i) return ERROR; s = (LinkList)malloc(sizeof(Node)); s->data = e; s->next = p->next; p->next = s; return OK; } /* 5.順序單鏈表刪除操作 */ /* 宣告一個指標p指向連結串列的頭結點,初始化j從1開始; 當 j<i 時,就遍歷連結串列,讓p的指標向後移動,不斷指向下一個結點,j累加1; 若到連結串列末端p為空,則說明第i個節點不存在; 否則查詢成功,將欲刪除的結點p->next賦給q; 單鏈表的插入標準語句p->next = q->next; 將q結點中的資料賦值給e,作為返回; 釋放結點q; 返回成功。 */ Status ListDelete(LinkList *L,int i,ElemType *e) { int j; LinkList p,q; p = *L; j = 1; while( p->next && j < i) /* 尋找第i-1個結點,下一結點不能為空 */ { p = p->next; ++j; } if( !(p->next) || j> i) return ERROR; q = p->next; p->next = q->next; *e = q->data; free(q); return OK; } /* 6.判斷順序單鏈表釋放為空 */ Status ListEmpty(LinkList L) { if(L->next) return FALSE; else return TRUE; } /* 7.順序單鏈表整表建立:頭插法 */ /* 宣告一個指標p和計數器變數i; 初始化一個空連結串列L; 讓L的頭結點的指標指向NULL,即建立一個帶頭結點的單鏈表; 迴圈: 生成一個新結點賦值給p; 隨機生成一個數字賦值給p的資料域p->data; 將p插入到頭結點與前一新結點之間p->next = (*L)->next;(*L)->next = p;; */ void CreateListHead(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)malloc(sizeof(Node)); p->data = rand()%100 + 1; p->next = (*L)->next; (*L)->next = p; } } /* 8.順序單鏈表整表建立:尾插法 */ /* 宣告指標p,r和計數器變數i; 初始化一個空連結串列L,r記錄前一新結點位置; 迴圈: 生成一個新結點賦值給p; 隨機生成一個數字賦值給p的資料域p->data; 將p插入到頭結點與前一新結點之間r->next = p;r = p;; */ void CreateListTail(LinkList *L,int n) { LinkList p,r; int i; srand (time (0)); *L = (LinkList) malloc (sizeof(Node)); r = *L; for( i = 0; i <n; i++ ) { p = (Node *) malloc (sizeof(Node)); p->data = rand()%100 + 1; r->next = p; r = p; } r->next = NULL; /* 表示當前連結串列結束 */ } /* 9.順序單鏈表整表刪除:從前向後刪除 */ /* 宣告指標p,q; 將第一個結點賦值給p; 迴圈: 將下一結點賦值給q;釋放q;將賦值給p. */ Status ClearList(LinkList *L) { LinkList p,q; p = (*L)->next; while( p ) { q = p->next; free(p); p = q; } (*L)->next = NULL; /* 表示當前連結串列結束 */ return OK; } /* 10.遍歷順序單鏈表 */ Status ListTraverse(LinkList L) { LinkList p=L->next; while(p) { printf("%d ",(p->data) ); p=p->next; } printf("\n"); return OK; } /* 11.順序單鏈表長度 */ int ListLength(LinkList L) { int i=0; LinkList p=L->next; /* p指向第一個結點 */ while(p) { i++; p=p->next; } return i; } int main() { LinkList L; ElemType e; Status i; int j; i=InitList(&L); printf("初始化L後:ListLength(L)=%d\n\n",ListLength(L)); for(j=1;j<=5;j++) i=ListInsert(&L,1,j); printf("在L的表頭依次插入1~5後:L.data="); i = ListTraverse(L); printf("\n"); printf("ListLength(L)=%d \n",ListLength(L)); i=ListEmpty(L); printf("L是否空:i=%d(1:是 0:否)\n\n",i); i=ClearList(&L); printf("清空L後:ListLength(L)=%d\n",ListLength(L)); i=ListEmpty(L); printf("L是否空:i=%d(1:是 0:否)\n\n",i); for(j=1;j<=10;j++) ListInsert(&L,j,j); printf("在L的表尾依次插入1~10後:L.data="); i = ListTraverse(L); printf("\n"); ListInsert(&L,1,0); printf("在L的表頭插入0後:L.data="); i=ListTraverse(L); printf("ListLength(L)=%d \n",ListLength(L)); printf("\n"); GetElem(L,5,&e); printf("第5個元素的值為:%d\n\n",e); for(j=12;j>=10;j--) { i=ListDelete(&L,j,&e); /* 刪除第j個數據 */ if(i==ERROR) printf("刪除第%d個數據失敗\n",j); else printf("刪除第%d個的元素值為:%d\n",j,e); } printf("依次輸出L的元素:"); ListTraverse(L); printf("\n"); i=ClearList(&L); printf("\n清空L後:ListLength(L)=%d\n",ListLength(L)); CreateListHead(&L,10); printf("整體建立L的元素(頭插法):"); ListTraverse(L); printf("\n"); i=ClearList(&L); printf("\n刪除L後:ListLength(L)=%d\n",ListLength(L)); CreateListTail(&L,10); printf("整體建立L的元素(尾插法):"); ListTraverse(L); printf("\n"); return 0; }