1. 程式人生 > 實用技巧 >單向迴圈連結串列

單向迴圈連結串列

單向迴圈連結串列

 單向連結串列是最簡單的線性鏈式儲存結構。可以通過頭結點遍歷整個連結串列。

 如上圖所示,單向迴圈連結串列就是申請的一塊塊堆空間,通過指標將其串聯起來,其中head指標存在棧空間,其內容存的是堆空間頭結點的地址,所有操作都需要通過head指標來實現。
 使用結構體來實現單向迴圈連結串列,結構體中有資料域和指標域兩個部分,其中資料域用來儲存資料,指標域是指向下一個資料的。

    typedef struct sgl_crclist{

        int data;
        struct sgl_crclist *next;
    }my_sgl_crclist, *p_sgl_crclist;  

頭節點設計


 新建一個單向迴圈連結串列,將其指標返回作為指向頭結點的指標head。

    p_sgl_crclist init_crclist(){

        p_sgl_crclist head = new_node_crclist(); //新建一個節點作為頭結點
        head->next = head;
        return head;
    }

新建節點

 呼叫calloc函式新建一個節點,該函式返回新建節點的地址,方便後續操作。

    p_sgl_crclist new_node_crclist(){

        p_sgl_crclist new = calloc(1, sizeof(my_sgl_crclist));

        if(NULL == new)
        {
            return NULL;
        }
        return new;
    }

插入資料

頭插法

    bool add_crclist(p_sgl_crclist head){

        int data;
        p_sgl_crclist new_node = new_node_crclist();  //新建節點
        p_sgl_crclist pos = head;

        printf("請輸入需要頭插的資料:");
        scanf("%d", &data);
        while('\n' != getchar());
        new_node->data = data;

        new_node->next = head->next;
        head->next = new_node;
    }

尾插法

    bool add_crclist_tail(p_sgl_crclist head){

        int data;
        p_sgl_crclist new_node = new_node_crclist();
        p_sgl_crclist pos = head;

        printf("請輸入需要尾插的資料:");
        scanf("%d", &data);
        while('\n' != getchar());
        new_node->data = data;

        while(pos->next != head)
        pos = pos->next;


        new_node->next = head;
        pos->next = new_node;
    } 

列印連結串列資料

 一個一個節點移動指標pos,並取出裡面的資料將其打印出來。

    void display_crclist(p_sgl_crclist head){

        p_sgl_crclist pos = head->next;

        for(int i = 0; pos != head; i++){

            printf("節點%d的資料為:%d\n", i, pos->data);
            pos = pos->next;
        }
    }

查詢資料

 查詢連結串列中是否有某個資料,有的話返回該資料所在節點的地址。

    p_sgl_crclist find_data(p_sgl_crclist head, int fdata){

        p_sgl_crclist pos = head->next;
        while(pos !=  head){

            if(pos->data == fdata){

                return pos;
            }
            else{
                pos = pos->next;
            }
        }

        printf("No data to found\n");
        return NULL;
    }

刪除資料

 刪除節點中的指定資料,此函式將呼叫函式find_data,用來獲取指定資料所在的節點地址。

    bool del_node_data(p_sgl_crclist head){

        int del_data;
        p_sgl_crclist delnode;
        p_sgl_crclist pos = head;

        printf("請輸入需要刪除的資料:\n");
        scanf("%d", &del_data);
        while('\n' != getchar());

        delnode = find_data(head, del_data);
        if(delnode == NULL)
            return NULL;

        while(pos->next != delnode){

            pos = pos->next;
            if(pos == NULL){

                printf("node is error\n");
                return NULL; 
            }
        }
        pos->next = delnode->next;
        delnode->next = NULL;
        return true;
    }

更改資料

 將連結串列中的某個資料修改成指定資料,此函式將呼叫find_data,用來獲取需要修改資料所在節點的地址。獲取到地址後判斷不為空時,直接修改即可。

    bool mod_node_data(p_sgl_crclist head){

        int old_data;
        int new_data;

        p_sgl_crclist modnode;

        printf("請輸入需要更改的舊資料和新資料:");
        scanf("%d %d", &old_data, &new_data);
        while('\n' != getchar());
        modnode = find_data(head, old_data);
        if(modnode == NULL)
           return false;

        modnode->data = new_data;
        return true;
    }

測試程式碼

    int test(){

        p_sgl_crclist head = init_crclist();
        add_crclist(head);
        add_crclist(head);
        add_crclist(head);
        add_crclist(head);
        add_crclist(head);
        display_crclist(head);
        mod_node_data(head);
        display_crclist(head);
        .....
        .....
        return 0;
    }