使用C語言寫帶頭結點的鏈表,含有創建、輸出、查找、刪除、插入、合併

今天有一位學弟在網上向我求助,讓我幫他寫c語言帶頭結點的鏈表題目。
我想了想,c語言我有一年半載沒有接觸了。正好溫習溫習一下,就寫下此博客,來回顧一下我學習c語言的汗(Lei)水(Shui)與快(Tong)樂(Ku)。

那些帶頭結點的鏈表的題目

我先展示一下那位學弟的題目吧!
編程實現如下函數:
1、創建一個帶頭結點的單鏈表;
2、打印輸出該單鏈表;
3、在單鏈表中查找元素x,找到後則【在x之前】插入元素y
4、假設單鏈表是有序的,向該單鏈表插入元素x,使得插入後依舊有序;
5、刪除單鏈表中值爲x的所有元素
6、給定兩個升序的單鏈表ha、hb,將其合併爲【升序的】hc。要求:利用原表空間(即hc中的結點從ha、hb中摘取,不能再重新分配空間)
7、給定兩個升序的單鏈表ha、hb,將其合併爲【降序的】hc。要求:利用原表空間(即hc中的結點從ha、hb中摘取,不能再重新分配空間)
8、將單鏈表中的最小值結點【摘除】,插入該單鏈表的頭(即作爲該單鏈表的第一個元素)。
我們應該知道帶頭結點的鏈表和不帶頭結點的鏈表之間的差別:帶頭結點的鏈表就是犧牲一個空間來方便鏈表的增、刪、改、找。我們討論的情況就能更少一些,相對應的代碼量也會更少一些。
我們現在就各項突破這些題目!!!

必要代碼

我們做鏈表題目時,總時要有公共部分來支撐,就像“打地基”一樣,沒有把“底層”做好,很難去進行下一步操作。所以我把必要的代碼稱爲公共部分。就是這些代碼幾乎每一道題都要用上。

定義一個結構體

#include <stdio.h>
#include <stdlib.h>
typedef int datatype;
 typedef struct link_node{
   datatype info;
   struct link_node *next;
 }node;
typedef node *linklist;

首先 typedef int datatype; 就是給int 取一個別名,這個別名叫做 datatype。那麼datatype 就有和int 一樣的功能。
struct 就是結構體的意思,所以我們用struct定義一個結構體,毫無違和感。
typedef struct link_node{…} node;就是給struct link_node{…}這個結構體取個別名叫做node。
以前我一直搞不懂*struct link_node next; 這個語句是什麼意思。
現在想想倒是有了一個理解:官方一些就是將next聲明爲指向link_node 的指針。就是指針next指向link_node。
通俗一些的理解:就好比老鷹抓小雞遊戲裏的“小雞們”。每一個人的手抓住前一個人的衣角,手相當於指針next,衣角相當於link_node。這樣一個一個相連,就成了C語言的鏈表。不知道這樣理解形象不形象。如果還有更好的理解,可以在評論區裏評論。

創建一個帶頭結點的單鏈表

/***************************************
函數名稱:creatbyqueue()
函數功能:尾插法建立帶頭結點的單鏈表
備註:第一題答案,公共函數,之後每題必用
***************************************/
linklist creatbyqueue()
{
    linklist head,r,s;
    datatype x;
    head=r=(linklist)malloc(sizeof(node));
    head->next=NULL;
    printf("請輸入整數序列(空格分開,以0結束):\n");
    scanf("%d",&x);
    while (x!=0)
    {
         s=(linklist)malloc(sizeof(node));
         s->info=x;
         r->next=s;
         r=s;
         scanf("%d",&x);
   }
    r->next=NULL;
    return head;
}

這是用尾插法建立帶頭結點的單鏈表。就像排隊一樣,先進先出,先輸入就可以先輸出。
具體怎麼實現的,用文字難以描述,等我有了充足的時間會在補全來的。之後我的解析更多的在代碼

既然有尾插法,那就有頭插法。頭插法相對來講更簡單一些,但是輸出時確實倒序輸出。

/******************************************
函數名稱:creatbystack() 
函數功能:頭插法建立帶頭結點的單鏈表 
******************************************/
linklist creatbystack()
{

    linklist  head,s;
    datatype x;

    head=(linklist)malloc(sizeof(node));
    head->next=NULL;

    printf("請輸入整數序列(空格分開,以0結束):\n");
    scanf("%d",&x);
    while (x!=0)
    {
        s=(linklist)malloc(sizeof(node));
        s->info=x;

        s->next=head->next;
        head->next=s;

        scanf("%d",&x);
    }
    return head;
}

打印輸出該單鏈表

/**********************************
函數名稱:print()
函數功能:輸出帶頭結點的單鏈表
備註:第二題答案,公共函數,之後每題必用
**********************************/
void print(linklist head)
{
    linklist p;
    int i=0;
    p=head->next;
    printf("List is:\n");
    while(p)
    {
        printf("%7d",p->info);
        i++;
        if (i%10==0)    printf("\n");
        p=p->next;
    }
    printf("\n");
}

釋放鏈表內存空間(容易忘記)

/**********************************
函數名稱:delList()
函數功能:釋放帶頭結點的單鏈表
備註:公共函數,之後每題必用。(容易忘記寫的一個函數)
**********************************/
void delList(linklist head)
{ linklist p=head;
  while (p)
  { head=p->next;
    free(p);
    p=head;
  }
}

題目

前三道題答案

題目:
1、創建一個帶頭結點的單鏈表;
2、打印輸出該單鏈表;
3、在單鏈表中查找元素x,找到後則【在x之前】插入元素y

第三道題核心代碼
/***********************************
函數名稱:find_x_insert_y()
函數功能:查找元素x,在x前面插入y。
備註:第三題答案
**********************************/
linklist find_x_insert_y(linklist chain, datatype x, datatype y)
{
    linklist q, pre = chain;
    q = chain->next;
    while (q && q->info != x)  //沒找完並且沒找到
    {
        pre = q;
        q = q->next;
    }
    if (q)   //表示q->info == x,即找到了x,那麼就在x前面插入y
    {
        linklist num;
        num = (linklist)malloc(sizeof(node));
        num->info = y;
        num->next = pre->next;
        pre->next = num;
    }
    else    //表示沒有找到x;
    {
        printf("抱歉!沒有找到x~~");
    }
    return chain;
}
前三道題的主函數代碼
int main()
{
    linklist chain;
    datatype y, x;
    //1、創建一個帶頭結點的單鏈表;(尾插法)
    chain = creatbyqueue();
    //2、打印輸出該單鏈表;
    print(chain);
    //3、在單鏈表中查找元素x,找到後則【在x之前】插入元素y
    printf("請輸入你要查找的值:");
    scanf("%d", &x);
    printf("請輸入要插入的值:");
    scanf("%d", &y);
    chain = find_x_insert_y(chain, x, y);
    printf("打印查看\n");
    print(chain);
    printf("釋放鏈表!\n");
    delList(chain);
    return 0;
}

第四道題答案

4、假設單鏈表是有序的,向該單鏈表插入元素x,使得插入後依舊有序;

第四道題核心代碼

/************************************************
函數名稱:insert_x()
函數功能:假設單鏈表是有序的,向該單鏈表插入元素x,使得插入後依舊有序;
備註:第四題答案。
************************************************/
linklist insert_x(linklist chain ,datatype x)
{
    linklist pre=chain,q,sert;
    q=chain->next;
    while(q&&q->info<x)  //沒找完並且小於x
    {
        pre=q;
        q=q->next;
    }
    if(q)  //表示q->info >= x,即找到了x,那麼就在q->info前面插入x
    {
        sert=(linklist)malloc(sizeof(node));
        sert->info=x;
        sert->next=pre->next;
        pre->next=sert;
    }
    else  //表示x比整個鏈表中的數都大,所以要插在鏈表的末尾。
    {
        sert=(linklist)malloc(sizeof(node));
        sert->info=x;
        pre->next=sert;
        sert->next=q;
    }
    return chain;
}
第四道題主函數代碼
int main()
{
    linklist chain;
    datatype x;
    //創建一個帶頭結點的單鏈表;(尾插法)
    chain = creatbyqueue();
    printf("打印查看\n");
    print(chain);
    printf("請輸入要插入的值:");
    scanf("%d", &x);
    //4、假設單鏈表是有序的,向該單鏈表插入元素x,使得插入後依舊有序;
    insert_x(chain, x);
    printf("打印查看\n");
    print(chain);
    printf("釋放鏈表!\n");
    delList(chain);
    return 0;
}

第五道題答案

5、刪除單鏈表中值爲x的所有元素

第五道題核心代碼
/**************************************
函數名稱:delete_all_x()
函數功能:刪除單鏈表中值爲x的所有元素
備註:第五題答案。
***************************************/
void delete_all_x(linklist chain, datatype x)
{
    linklist pre,q;
    int flag = 0;
    pre=chain;
    q=chain->next;
    while(q)
    {
        while (q &&q->info!=x)      //沒找完並且沒找到
        {
            pre=q;
            q=q->next;
        }
        if (q)          //表示q->info == x,那麼就刪除該結點
        {
            flag ++;
            pre->next=q->next;
            free(q);
            q=pre->next;   //刪除後q回到pre的後繼結點
        }
    }
    if (flag==0)
        printf("未找到值爲x=%d的結點!所以沒有刪除結點!\n", x);
    else
        printf("值爲x=%d的結點一共有%d個,現已全部刪除!\n", x, flag);
第五道題主函數代碼
int main()
{   datatype x;
    linklist chain;
    chain=creatbyqueue();
    printf("打印查看\n");
    print(chain);
    printf("請輸入要刪除的值:");
    scanf("%d",&x);
    //5、刪除單鏈表中值爲x的所有元素
    delete_all_x(chain, x);
    printf("打印查看\n");
    print(chain);
    printf("釋放鏈表!\n");
    delList(chain);
    return 0;
}

第六道題答案

6、給定兩個升序的單鏈表ha、hb,將其合併爲【升序的】hc。要求:利用原表空間(即hc中的結點從ha、hb中摘取,不能再重新分配空間)

第六道題核心代碼
/*****************************************
函數名稱:chain_ascend()
函數功能:給定兩個升序的單鏈表ha、hb,將其合併爲【升序的】hc。要求:利用原表空間(即hc中的結點從ha、hb中摘取,不能再重新分配空間)
備註:第六題答案
*****************************************/
linklist chain_ascend(linklist ha,linklist hb)
{
        linklist hc,rc,p,q;
        hc=rc=(linklist)malloc(sizeof(node));
        p=ha->next;
        q=hb->next;
        while (p && q)
        {
            if (p->info<q->info)
            {
                ha->next=p->next;
                rc->next=p;
                rc=p;
                p=ha->next;
            }
            else
            {
                hb->next=q->next;
                rc->next=q;
                rc=q;
                q=hb->next;
            }
        }
        if (p)  rc->next=p;
        if (q) rc->next=q;
        free(ha);
        free(hb);
        return hc;
}
第六道題主函數代碼
int main()
{
    linklist ha,hb,hc;
    //尾插法建立單鏈表,請輸入升序序列
    ha=creatbyqueue();
    hb=creatbyqueue();
    printf("打印查看\n");
    print(ha);
    print(hb);
    //升序合併到 hc
    hc=chain_ascend(ha,hb);
    printf("打印查看合併升序鏈表\n");
    print(hc);
    printf("釋放鏈表!\n");
    delList(hc);
    return 0;
}

第七道題答案

7、給定兩個升序的單鏈表ha、hb,將其合併爲【降序的】hc。要求:利用原表空間(即hc中的結點從ha、hb中摘取,不能再重新分配空間)

第七道題核心代碼
/*************************************
函數名稱:chain_descend()
函數功能:給定兩個升序的單鏈表ha、hb,將其合併爲【降序的】hc。要求:利用原表空間(即hc中的結點從ha、hb中摘取,不能再重新分配空間)
備註:第七題答案
**************************************/
linklist chain_descend(linklist ha,linklist hb)
{
        linklist hc,p,q;
        hc=(linklist)malloc(sizeof(node));
        hc->next=NULL;
        p=ha->next;
        q=hb->next;
        while (p && q)
        {
            if (p->info<q->info)
            {
                ha->next=p->next;
                p->next=hc->next;
                hc->next=p;
                p=ha->next;
            }
            else
            {
                hb->next=q->next;
                q->next=hc->next;
                hc->next=q;
                q=hb->next;
            }
        }
        while (p)
        {
                ha->next=p->next;
                p->next=hc->next;
                hc->next=p;
                p=ha->next;
        }
        while (q)
        {
                hb->next=q->next;
                q->next=hc->next;
                hc->next=q;
                q=hb->next;
        }
        free(ha);
        free(hb);
        return hc;
}
第七道題主函數代碼
int main()
{
    linklist ha,hb,hc;
    //尾插法建立單鏈表,請輸入升序序列
    ha=creatbyqueue();
    hb=creatbyqueue();
    printf("打印查看\n");
    print(ha);
    print(hb);
    //降序合併到 hc
    hc=chain_descend(ha,hb);
    printf("打印查看合併降序鏈表\n");
    print(hc);
    printf("釋放鏈表!\n");
    delList(hc);
    return 0;
}

第八道題答案

8、將單鏈表中的最小值結點【摘除】,插入該單鏈表的頭(即作爲該單鏈表的第一個元素)。

第八道題核心代碼
/***************************************
函數名字:find_min_insert_head()
函數功能:將單鏈表中的最小值結點【摘除】,插入該單鏈表的頭(即作爲該單鏈表的第一個元素)。
備註:第八題答案
****************************************/
linklist find_min_insert_head(linklist chain)
{
    linklist head=chain, pre = chain, q=chain->next;
    datatype x;
    x = q->info;
    //先找到最小值
    while (q)
    {
        if (q->info<=x)
            x = q->info;
        q = q->next;
    }
    //初始化
    q = chain->next;
    while (q->info != x)
    {
        pre = q;
        q = q->next;
    }
    pre->next = q->next;
    q->next = head->next;
    head->next = q;
    return chain;
}
第八道題主函數代碼
int main()
{
    linklist chain;
    chain = creatbyqueue();
    printf("打印查看\n");
    print(chain);
    chain = find_min_insert_head(chain);
    printf("打印查看將最小值放入頭節點的鏈表\n");
    print(chain);
    printf("釋放鏈表!\n");
    delList(chain);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章