真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

單向鏈表c語言實(shí)現(xiàn)

  1. 定義(引用百度百科)
    單鏈表是一種鏈?zhǔn)酱嫒〉臄?shù)據(jù)結(jié)構(gòu),用一組地址任意的存儲(chǔ)單元存放線性表中的數(shù)據(jù)元素。鏈表中的數(shù)據(jù)是以結(jié)點(diǎn)來表示的,每個(gè)結(jié)點(diǎn)的構(gòu)成:元素(數(shù)據(jù)元素的映象) + 指針(指示后繼元素存儲(chǔ)位置),元素就是存儲(chǔ)數(shù)據(jù)的存儲(chǔ)單元,指針就是連接每個(gè)結(jié)點(diǎn)的地址數(shù)據(jù)。
  2. 場(chǎng)景

在實(shí)際生產(chǎn)中,有可能在軟件啟動(dòng)后,對(duì)一些數(shù)據(jù)進(jìn)行多態(tài)擴(kuò)容,比如,網(wǎng)卡收發(fā)包的時(shí)候,從協(xié)議棧上產(chǎn)生一個(gè)需求的包,需要暫時(shí)排隊(duì),等網(wǎng)卡把數(shù)據(jù)發(fā)送出去后,在在隊(duì)列里處理,所以這種利用堆中分散的內(nèi)存,以結(jié)點(diǎn)為單位的數(shù)據(jù)結(jié)果是有一定的意義的。

創(chuàng)新互聯(lián)公司專注于企業(yè)全網(wǎng)整合營(yíng)銷推廣、網(wǎng)站重做改版、豐城網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、H5場(chǎng)景定制、商城網(wǎng)站制作、集團(tuán)公司官網(wǎng)建設(shè)、外貿(mào)網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為豐城等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。

  1. C語言實(shí)現(xiàn),聊作記錄

鏈表的數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)

typedef struct node
{
        int data;                                           //數(shù)據(jù)域
        struct node *next;                          //指針域
}NODE_t;

鏈表的創(chuàng)建

    NODE_t *CreatNodeList()
{
    NODE_t *head = NULL;

    head = (NODE_t *)malloc(sizeof(NODE_t));
    if(!head)
        exit(-1);
    head->next = NULL;

    return head;
}

鏈表的插入,頭插入,有個(gè)頭節(jié)點(diǎn),方便遍歷,處理

int InsertNode(NODE_t *head,int data)
{
    NODE_t *cur = NULL;

    if(!head)
        exit(-1);

    cur = (NODE_t *)malloc(sizeof(NODE_t));
    if(!cur)
        exit(-1);

    cur->data = data;
    //cur 插入到 head 和 head->next 之間
    cur->next = head->next;
    head->next = cur;

    return 0;
}

結(jié)點(diǎn)的查找

NODE_t *findNode(NODE_t *head,int data)
{
    head = head->next;
    while(head)
    {
        if(head->data == data)
        {
            break;
        }
        head = head->next;
    }
    if(head == NULL)
    {
        printf("sorry,%d is not in the list\n",data);
    }

    return head;
}

結(jié)點(diǎn)的刪除

    int DeleteNodeOfList(NODE_t *head,NODE_t *pfind)
{
    // 首先找到這個(gè)需要?jiǎng)h除指針的前一個(gè)節(jié)點(diǎn)的指針
    // 因?yàn)閜find 的合法性在外面判斷,此處不再判斷
    while(head->next != pfind)
    {
        head = head->next;
    }

    head->next = pfind->next;
    free(pfind);
    pfind = NULL;

    return 0;
}

這里的刪除,假設(shè)結(jié)點(diǎn)數(shù)目很多,則會(huì)造成一個(gè)問題,單鏈表只能一個(gè)方向,則需要找到需要?jiǎng)h除的節(jié)點(diǎn)的前驅(qū)指針,則需要從頭開始遍歷,比較浪費(fèi)資源,所以,這個(gè)地方存在優(yōu)化空間,就是,一旦擁有需要?jiǎng)h除的節(jié)點(diǎn),則可以這么操作

  • 將需要?jiǎng)h除節(jié)點(diǎn)后驅(qū)結(jié)點(diǎn)的數(shù)據(jù)域數(shù)據(jù)拷貝至當(dāng)前的刪除節(jié)點(diǎn)數(shù)據(jù)域
  • 刪除刪除節(jié)點(diǎn)的后驅(qū)指針

優(yōu)化版本如下:

// 優(yōu)化點(diǎn): 不必每次都遍歷所有的節(jié)點(diǎn),找到前驅(qū)節(jié)點(diǎn)
// 將這個(gè)需要?jiǎng)h除的節(jié)點(diǎn)的后驅(qū)節(jié)點(diǎn)的數(shù)據(jù)域拷貝過來,然后刪除這個(gè)后驅(qū)節(jié)點(diǎn)
int DeleteNodeOfList_Better(NODE_t *head,NODE_t *pfind)
{
    NODE_t *p = pfind->next;

    //最后一個(gè)節(jié)點(diǎn),它其后沒有后驅(qū)節(jié)點(diǎn),所以需要從頭遍歷,找到它的前置節(jié)點(diǎn)
    if(pfind->next == NULL)
    {
        while(head->next != pfind)
        {
            head = head->next;
        }

        head->next = pfind->next;
        free(pfind);
        pfind = NULL;
    }
    else //對(duì)于除最后一個(gè)節(jié)點(diǎn)的外的其他位置節(jié)點(diǎn),則使用覆蓋后刪除后置節(jié)點(diǎn)的方式實(shí)現(xiàn)刪除
    {

        pfind->data = pfind->next->data;
        pfind->next = pfind->next->next;

        free(p);
        p = NULL;
    }

    return 0;
}

一旦找到結(jié)點(diǎn)的指針操作只是針對(duì)數(shù)據(jù)域的一個(gè)操作,比較便捷
結(jié)點(diǎn)的修改

int UpdateNode(NODE_t *head,int olddata,int newdata)
{
    NODE_t *p = findNode(head,olddata);
    if(p)
    {
        p->data = newdata;
    }

    return 0;
}

遍歷打印顯示

void showList(NODE_t *head)
{
    head = head->next;
    while(head)
    {
        printf("%d ==> ",head->data);
        head = head->next;
    }
    printf("end..\n");
}

鏈表的排序

int sortList(NODE_t *head)
{
    int i = 0,j = 0;
    int listlen = 0;
    int tmpData = 0;
    NODE_t *p = NULL;

    // 使用冒泡排序,不動(dòng)指針域,比較數(shù)據(jù)域,使用臨時(shí)變量,將有大小之別的節(jié)點(diǎn)的數(shù)據(jù)域交換
    // 得到鏈表長(zhǎng)度,方便冒泡
    listlen = ListNodeLen(head);

    // 指到首節(jié)點(diǎn)
    p = head->next;
    for(i = 0;i < listlen-1;i++)
    {
        // 每一輪從頭開始
        p = head->next;
        for(j = 0;jdata > p->next->data)
            {
                tmpData = p->data;
                p->data = p->next->data;
                p->next->data = tmpData;
            }
            p = p->next;
        }
    }

    return 0;
}

這里只是demo,鏈表的數(shù)據(jù)域很小,所以這種排序方式可以,但是當(dāng)數(shù)據(jù)域的很大時(shí),直接使用這種排序,涉及到大量的搬運(yùn)內(nèi)存,將會(huì)導(dǎo)致很大的資源消耗,所以這個(gè)地方是存在優(yōu)化的空間的,比如直接改變需要交換結(jié)點(diǎn)的指向關(guān)系
代碼如下

int sortList_better(NODE_t *head)
{
    // 當(dāng)數(shù)據(jù)域很大的時(shí)候,搬遠(yuǎn)數(shù)據(jù)很耗費(fèi)資源,但是指針就4個(gè)字節(jié),
    // 所以改變指針域的相互指向,就可解決問題
    // 思路如下:
    // 還是使用冒泡比較,當(dāng)需要交換時(shí),將兩個(gè)節(jié)點(diǎn)的指針域指向關(guān)系互換

    int i = 0,j = 0;
    int listlen = 0;
    NODE_t *p = NULL;
    NODE_t *q = NULL;
    NODE_t *tmp = NULL;
    listlen = ListNodeLen(head);

    for(i = 0;i next;
        q = p->next;                    // q 永遠(yuǎn)指向p結(jié)點(diǎn)的下一個(gè)結(jié)點(diǎn)
        for(j = 0;j data > q->data)
            {
                //                NODE_t *tmp = prePointerOfNode(head,p);
//                現(xiàn)在有三個(gè)結(jié)點(diǎn),prep p    q 他們分別代表的含義是

//                p 為當(dāng)前結(jié)點(diǎn)
//                prep為p結(jié)點(diǎn)的前驅(qū)結(jié)點(diǎn)
//                q 為p結(jié)點(diǎn)的后續(xù)結(jié)點(diǎn)

//                現(xiàn)在需要將p 和 q的順序做對(duì)調(diào),只需要改變其指向關(guān)系即可
//                1. 將prep 的下一個(gè)結(jié)點(diǎn)指向到q
//                2. 將p結(jié)點(diǎn)后續(xù)結(jié)點(diǎn)指向q的后續(xù)結(jié)點(diǎn)
//                3. 在第二步里已經(jīng)在q的后續(xù)結(jié)點(diǎn)的已經(jīng)找到,所以這個(gè)時(shí)候?qū)的后續(xù)結(jié)點(diǎn)指向p,
//                這樣子,就將p和q的順序?qū)φ{(diào)過了
                tmp->next = q;
                p->next = q->next;
                q->next = p;

//                因?yàn)閜和q的順序已經(jīng)對(duì)調(diào)過了,為保證順序,將p和q的順序做一次對(duì)調(diào),
//                確保q是p的下一個(gè)結(jié)點(diǎn)
                /*
                    注意p和q都是臨時(shí)變量,所以,這個(gè)地方并非對(duì)結(jié)點(diǎn)的對(duì)調(diào),只是臨時(shí)指針的對(duì)調(diào),就是將q對(duì)于結(jié)點(diǎn)的指針放到p這個(gè)臨時(shí)變量里
                    ,原來p對(duì)應(yīng)的結(jié)點(diǎn)指針放到q這個(gè)臨時(shí)變量中
                */
                NODE_t *t = NULL;
                t = p;
                p = q;
                q = t;
            }
//            向下走一個(gè)
            tmp = tmp->next;
            p = p->next;
            q = p->next;
        }
    }

    return 0;
}

鏈表的逆序

void ReverseList(NODE_t *head)
{
    //將頭指針和其他鏈表割裂,這樣子就是一個(gè)空鏈表 和一個(gè)無頭的鏈表
    // 然后將另一個(gè)鏈表的每個(gè)結(jié)點(diǎn)拆出來,然后使用頭插法插入到空鏈中,這樣子最后就實(shí)現(xiàn)了鏈表的逆向排序

    NODE_t *HeadNextNode = head->next;
    head->next = NULL; //分割鏈表,分成一個(gè)空鏈和一個(gè)鏈表

    // 將第二個(gè)鏈表的每一個(gè)結(jié)點(diǎn)分別插入到空鏈的頭部
    for(HeadNextNode;HeadNextNode !=NULL;HeadNextNode = HeadNextNode->next)
    {
        InsertNode(head,HeadNextNode->data);
    }
}

這個(gè)思路很好,不易出錯(cuò),如果貿(mào)然的從指向關(guān)系上入手,很容易把自己繞暈

鏈表的銷毀

void DestoryNodeList(NODE_t *head)
{
    NODE_t *p = NULL;

    while(head)
    {
        p = head->next;
        free(head);
        head = p;
    }
}

當(dāng)前文章:?jiǎn)蜗蜴湵韈語言實(shí)現(xiàn)
URL標(biāo)題:http://weahome.cn/article/pgssce.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部