單鏈表的 C 語言實現
阿新 • • 發佈:2018-12-17
用 C 語言實現一個單鏈表,包含連結串列的建立、遍歷、插入、刪除、排序等常用操作
# include<stdio.h> # include<stdlib.h> # include<malloc.h> struct Node { int data;//資料域 struct Node * pNext;//指標域,存放下一個節點的地址 }; //函式宣告 struct Node * createList(void);//建立連結串列 void traverseList(struct Node * pHead);//遍歷輸出連結串列 bool isEmptyList(struct Node * pHead);//判斷連結串列是否為空 int size(struct Node * pHead);//連結串列長度 void sortList(struct Node * pHead);//連結串列排序 bool deleteList(struct Node * pHead, int pos, int * pVal);//刪除連結串列的節點 bool insertList(struct Node * pHead, int pos, int val);//增加一連結串列節點 int main(void) { int deleteValue;//被刪除的值 struct Node * pHead = NULL; //建立連結串列 pHead = createList(); if (NULL == pHead) { printf("連結串列分配記憶體失敗\n"); exit(-1); } //遍歷輸出連結串列 traverseList(pHead); if(insertList(pHead,4,88)) { printf("為連結串列新增了一個值\n"); traverseList(pHead); } if(deleteList(pHead,3,&deleteValue)) { printf("刪除了連結串列中的一個值 %d \n",deleteValue); traverseList(pHead); } else { printf("刪除失敗,沒有這個值"); } // if(isEmptyList(pHead)) // { // printf("連結串列為空\n"); // } // else // { // printf("連結串列不為空\n"); // } // int length = size(pHead); // printf("連結串列的長度是%d ",length); // sortList(pHead); // printf("排序後的陣列\n"); // traverseList(pHead); return 0; } struct Node * createList() { int i; int len; int val; struct Node * pHead = (struct Node *)malloc(sizeof(struct Node)); if (NULL == pHead) { printf("連結串列分配記憶體失敗,程式終止!\n"); exit(-1); } struct Node * pTail = pHead;//定義一個指標,永遠指向尾節點,初始時刻,pTail和pHead同時指向頭結點 pTail->pNext = NULL;//初始時刻,頭結點也是最後一個節點,指標域應為空 printf("請輸入需要建立的連結串列的長度:len= "); scanf("%d", &len); for (i=0; i<len; i++)//生成len個有效節點 { printf("請輸入第%d個節點的值:",i+1); scanf("%d",&val); //每一次迴圈建立一個節點,並把指標儲存在pNode指標變數中 struct Node * pNode = (struct Node *)malloc(sizeof(struct Node)); if (NULL == pNode) { printf("建立連結串列失敗,程式終止!\n"); exit(-1); } pNode->data = val;//填充資料域 pTail->pNext = pNode;//pTail指向的那個節點的指標域儲存新建立的節點的地址 pTail = pNode;//pTail儲存新建立的節點的地址,這樣可以保證pTail永遠指向最後一個節點 pNode->pNext = NULL;//最後一個節點的指標域置為空 } return pHead; } void traverseList(struct Node * pHead) { //方法一:先定義一個指標指向第一個節點,依次迴圈,看看這個指標所指向的節點的指標域是否為空,如果為空,則遍歷到最後了 // struct Node * p = pHead->pNext;//這樣p就儲存了首節點的地址,也就指向了第一個節點 // while(p != NULL) // { // printf("%d ",p->data); // p = p->pNext;//指標往下移一個節點 // } // printf("\n"); //方法二:或者直接用pHead指標迴圈也可以 while(pHead->pNext != NULL) { printf("%d ",pHead->pNext->data); pHead = pHead->pNext; } printf("\n"); return ; } bool isEmptyList(struct Node * pHead) { if(pHead->pNext == NULL)//pHead指標指向頭結點,頭結點的指標域為空,連結串列也就為空 { return true;//為空 } else { return false; } } int size(struct Node * pHead) { int len; if(isEmptyList(pHead)) { len= 0; return len; } while(pHead->pNext != NULL) { len++; pHead = pHead->pNext; } return len; } void sortList(struct Node * pHead) { int i,j,tmp; struct Node * p;//定義一前一後兩個指標 struct Node * q; int length = size(pHead); //類比陣列的氣泡排序 for (i=0,p=pHead->pNext; i<length-1; i++,p=p->pNext) { for (j=i+1,q=p->pNext; j<length; j++,q=q->pNext) { if(p->data > q->data) { tmp = p->data; p->data = q->data; q->data = tmp; } } } } bool insertList(struct Node * pHead, int pos, int val) { struct Node * p = pHead; int i = 0; //執行完while語句,此時的p已經指向了pos前的一個節點 while (NULL != p && i<pos-1) { p = p->pNext; i++; } if (i>pos-1 || NULL ==p) { return false; } struct Node * pNew = (struct Node *)malloc(sizeof(struct Node)); if (NULL == pNew) { printf("分配記憶體失敗,建立節點失敗\n"); exit(-1); } pNew->data = val;//為新節點資料域賦值 //如下兩行插入新節點 pNew->pNext = p->pNext; p->pNext = pNew; //或者用下面定義個臨時指標變數的方式 // struct Node * q = p->pNext; // p->pNext = pNew; // pNew->pNext = q return true; } bool deleteList(struct Node * pHead, int pos, int * pVal) { struct Node * p = pHead; int i = 0; while (NULL != p->pNext && i<pos-1) { p = p->pNext; i++; } if (i>pos-1 || NULL ==p->pNext) { return false; } *pVal = p->data;//儲存刪除的值,傳遞到主函式中,以備檢視 p->pNext = p->pNext->pNext; //或者用下面定義個臨時指標變數的方式 // struct Node * q = p->pNext; // *pVal = q->data; // p->pNext = p->pNext->pNext; // free(q); // q = NULL; return true; }