程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> C語言入門知識 >> C語言實現鏈表的基本操作

C語言實現鏈表的基本操作

編輯:C語言入門知識

鏈表在數據結構和算法中的重要性不言而喻。這裡我們要用C來實現鏈表(單鏈表)中的基本操作。對於鏈表的基本概念請參考《數據結構與算法之鏈表》這篇博客。

(1)定義單鏈表的節點類型

typedef int elemType ;

// 定義單鏈表結點類型
typedef struct ListNode{
    elemType element;      //數據域
    struct ListNode *next;   //地址域
}Node;
(2)初始化線性表
// 1.初始化線性表,即置單鏈表的表頭指針為空
void initList(Node *pNode){

    pNode = NULL;
    printf("%s函數執行,初始化成功\n",__FUNCTION__);
}
當聲明一個頭結點後,把該頭結點設置為空,即把數據域和地址域都設為空,即可完成該鏈表的初始化。

(3)創建線性表

// 2.創建線性表,此函數輸入負數終止讀取數據
Node *creatList(Node *pHead){

    Node *p1;//表頭節點,始終指向頭結點
    Node *p2;//表尾節點,始終指向鏈表的最後一個元素

    p1 = p2 = (Node *)malloc(sizeof(Node)); //申請新節點,分配空間
    if(p1 == NULL || p2 == NULL){

        printf("內存分配失敗\n");
        exit(0);
    }
    memset(p1,0,sizeof(Node));

    scanf("%d",&p1->element);    //輸入新節點的值
    p1->next = NULL;         //新節點的指針置為空
    while(p1->element > 0){        //輸入的值大於0則繼續,直到輸入的值為負
        if(pHead == NULL){       //空表,接入表頭
            pHead = p1;          //直接把p1作為頭結點,也可以理解為把pHead頭結點指向p1
        }else{
            p2->next = p1;       //非空表,接入表尾
        }
        p2 = p1;                //p1插入後,p1就是尾結點,所以p2要指向尾結點
        p1 = (Node *)malloc(sizeof(Node));    //再重申請一個節點
        if(p1 == NULL || p2 == NULL){

            printf("內存分配失敗\n");
            exit(0);
        }
        memset(p1,0,sizeof(Node));
        scanf("%d",&p1->element);
        p1->next = NULL;
    }
    printf("%s函數執行,鏈表創建成功\n",__FUNCTION__);
    return pHead;           //返回鏈表的頭指針
}
我這裡使用手動的方式輸入元素,直到輸入0或者負數停止。

(4)打印鏈表

// 3.打印鏈表,鏈表的遍歷
void printList(Node *pHead){
    if(NULL == pHead){   //鏈表為空
        printf("%s函數執行,鏈表為空\n",__FUNCTION__);
    }else{
        while(NULL != pHead){
            
            printf("%d ",pHead->element);
            pHead = pHead->next;
        }
        printf("\n");
    }
}
使用地址域順序打印即可。

(5)清空鏈表

// 4.清除線性表L中的所有元素,即釋放單鏈表L中所有的結點,使之成為一個空表
void clearList(Node *pHead){

    Node *pNext;            //定義一個與pHead相鄰節點,理解為當前節點的下一個節點
    if(pHead == NULL){
        printf("%s函數執行,鏈表為空\n",__FUNCTION__);
    }
    while(pHead->next != NULL){

        pNext = pHead->next;//保存下一結點的指針
        free(pHead);   //釋放當前節點
        pHead = pNext;      //指向下一個節點
    }
    printf("%s函數執行,鏈表已經清除\n",__FUNCTION__);
}
想要檢驗是否清空成功,可以使用(4)中的鏈表打印檢驗即可。

(6)計算鏈表長度

// 5.返回單鏈表的長度
int sizeList(Node *pHead){

    int size = 0;
    while(pHead != NULL){

        size++;
        pHead = pHead->next;
    }
    printf("%s函數執行,鏈表長度 %d \n",__FUNCTION__,size);
    return size;    //鏈表的實際長度
}
也就是計算有多少個節點。

(7)判斷鏈表是否為空

// 6.檢查單鏈表是否為空,若為空則返回1,否則返回0
int isEmptyList(Node *pHead){
    if(pHead == NULL){

        printf("%s函數執行,鏈表為空\n",__FUNCTION__);
        return 1;
    }
    printf("%s函數執行,鏈表非空\n",__FUNCTION__);

    return 0;
}

(8)查找鏈表某個位置元素
// 7.返回單鏈表中第pos個結點中的元素,若pos超出范圍,則停止程序運行
void getElement(Node *pHead, int pos){

    int i = 0;
    if(pos < 1){
        printf("%s函數執行,pos值非法\n",__FUNCTION__);
    }

    if(pHead == NULL){
        printf("%s函數執行,鏈表為空\n",__FUNCTION__);
    }

    while(pHead != NULL){

        i++;
        if(i == pos){
            break;
        }
        pHead = pHead->next;    //移到下一結點
    }
    if(i < pos){                  //pos值超過鏈表長度
        printf("%s函數執行,pos值超出鏈表長度\n",__FUNCTION__);
    }

    printf("%s函數執行,位置 %d 中的元素為 %d\n",__FUNCTION__,pos,pHead->element);
}

(9)返回某元素值在鏈表中的內存地址
// 8.從單鏈表中查找具有給定值x的第一個元素,若查找成功則返回該結點data域的存儲地址,否則返回NULL
elemType* getElemAddr(Node *pHead, elemType x){
    if(NULL == pHead){

        printf("%s函數執行,鏈表為空\n",__FUNCTION__);
        return NULL;
    }

    while((pHead->element != x) && (NULL != pHead->next)) {//判斷是否到鏈表末尾,以及是否存在所要找的元素
        pHead = pHead->next;
    }

    if((pHead->element != x) && (pHead != NULL)){
        //當到達最後一個節點
        printf("%s函數執行,在鏈表中未找到x值\n",__FUNCTION__);
        return NULL;
    }

    if(pHead->element == x){
        printf("%s函數執行,元素 %d 的地址為 0x%x\n",__FUNCTION__,x,&(pHead->element));
    }

    return &(pHead->element);//返回元素的地址
}

(10)修改某個節點的值

// 9.把單鏈表中第pos個結點的值修改為x的值,若修改成功返回1,否則返回0
int modifyElem(Node *pNode,int pos,elemType x){

    int i = 0;
    if(NULL == pNode){
        printf("%s函數執行,鏈表為空\n",__FUNCTION__);
        return 0;
    }

    if(pos < 1){

        printf("%s函數執行,pos值非法\n",__FUNCTION__);
        return 0;
    }

    while(pNode != NULL){

        i++;
        if(i == pos){
            break;
        }
        pNode = pNode->next; //移到下一結點
    }

    if(i < pos) {                 //pos值大於鏈表長度

        printf("%s函數執行,pos值超出鏈表長度\n",__FUNCTION__);
        return 0;
    }
    pNode->element = x;
    printf("%s函數執行\n",__FUNCTION__);

    return 1;
}
(11)表頭插入一個節點(頭節點)
// 10.向單鏈表的表頭插入一個元素
int insertHeadList(Node **pNode,elemType insertElem){

    Node *pInsert;
    pInsert = (Node *)malloc(sizeof(Node));
    memset(pInsert,0,sizeof(Node));
    pInsert->element = insertElem;
    pInsert->next = *pNode;
    *pNode = pInsert;          //頭節點*pNode指向剛插入的節點,注意和上一行代碼的前後順序;
    printf("%s函數執行,向表頭插入元素成功\n",__FUNCTION__);

    return 1;
}
(12)表尾插入一個節點
// 11.向單鏈表的末尾添加一個元素
int insertLastList(Node **pNode,elemType insertElem){

    Node *pInsert;
    Node *pHead;

    pHead = *pNode;
    pInsert = (Node *)malloc(sizeof(Node)); //申請一個新節點
    memset(pInsert,0,sizeof(Node));
    pInsert->element = insertElem;

    while(pHead->next != NULL){
        pHead = pHead->next;
    }
    pHead->next = pInsert;   //將鏈表末尾節點的下一結點指向新添加的節點

    printf("%s函數執行,向表尾插入元素成功\n",__FUNCTION__);
    
    return 1;
}
(13)測試函數
int main(int argc, const char * argv[]) {

    Node *pList;            //聲明頭結點

    initList(pList);       //鏈表初始化
    printList(pList);       //遍歷鏈表,打印鏈表

    pList = creatList(pList); //創建鏈表
    printList(pList);

    sizeList(pList);        //鏈表的長度
    printList(pList);

    isEmptyList(pList);     //判斷鏈表是否為空鏈表

    getElement(pList,3);  //獲取第三個元素,如果元素不足3個,則返回0
    printList(pList);

    getElemAddr(pList,5);   //獲得元素5的內存地址

    modifyElem(pList,4,1);  //將鏈表中位置4上的元素修改為1
    printList(pList);

    insertHeadList(&pList,5);   //表頭插入元素5
    printList(pList);

    insertLastList(&pList,10);  //表尾插入元素10
    printList(pList);

    clearList(pList);       //清空鏈表
    printList(pList);

    return 0;
}
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved