用鏈表實現集合的交集並集差集運算


題目來自某NJU同學的程序設計基礎作業

貼一下題目:

用鏈表建立兩個整數集合A和B(從鍵盤鍵入集合的元素,以-1結束,集合中沒有-1)。

分別編寫三個函數計算這兩個集合的。

  a.交集

  b.並集

  c.差集A-B

三個函數的計算結果為新的鏈表。

輸出這三個新鏈表。

做題心得

其實這道題用數組直接能秒殺掉,難度就在對於單鏈表的理解與應用。對指針和結構體有挺高的掌握要求。

之前沒好好學鏈表,總覺得數組能解決的事用數組,數組解決不了的用STL(stl永遠的神不接受反駁)

補了三天的鏈表,總算學得明白了一點,簡單把題過了一下。沒有用函數分段,其實分段一下很簡單。

P.S肥腸感謝雞哥龍神的鼎力相助!

直接po代碼,有錯誤或者其他更好的思路也希望dalao們可以帶帶

#include<stdio.h>
#include<stdlib.h>
struct node//鏈表結構體 
{
    int data;//數據域 
    struct node* next;//指向下一個結構體的指針 
};
node* create(int data)//新建鏈表項(新結構體) 
{
    node* newNode = (node*)malloc(sizeof(node));//給這個結構體開空間 
    newNode->data = data;//保存數據 
    newNode->next = NULL;//指針為空 
    return newNode;//返回新建的結構體 
}

int main()
{
    struct node *p,*q,*t,*h;//定義幾個臨時變量,會用到 
    int tmp;
    
    //輸入集合A 
    scanf("%d", &tmp);
    struct node* head_a = create(tmp);//頭節點 
    p = head_a;//p是臨時變量 
    while (scanf("%d", &tmp) && tmp != -1)//輸入數字,且當tmp=-1的時候結束 
    {
        struct node* a = create(tmp);//給鏈表A新建節點 
        p->next = a;//上一個節點的指針指向現在這個 
        p = a;//臨時變量變成現在這個 
    }
    
    //輸入集合A 
    scanf("%d", &tmp);
    struct node* head_b = create(tmp);//頭節點 
    p = head_b;//p是臨時變量 
    while (scanf("%d", &tmp) && tmp != -1)//輸入數字,且當tmp=-1的時候結束
    {
        struct node* b = create(tmp);//給鏈表A新建節點
        p->next = b;//上一個節點的指針指向現在這個
        p = b;//臨時變量變成現在這個 
    }
    
    struct node* head_jiao = create(-1);//定義交集的頭結點 
    struct node* head_bing = create(-1);//定義並集的頭結點 
    struct node* head_cha = create(-1);//定義差集的頭結點 
    
    /*
    交集思路:
    遍歷A,對A的每個元素 ,都與B中的元素進行一一對比
    類似於for循環中的
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            比較a和b
        }
    }
    */ 
     
    p=head_a;//p是臨時變量,從A的頭開始 
    t=head_jiao;//t是臨時變量,用來存交集的鏈表 
    while(p!=NULL)//鏈表A非空 ,遍歷A鏈表 
    {
        
        q=head_b;//q是臨時變量 ,從B的頭開始 
        while(q!=NULL)//鏈表B非空 ,遍歷B鏈表 
        {
            if(q->data==p->data)//B元素=A元素 
            {
                //如果a和b中有相同元素,則存進交集鏈表中 
                //以下操作與輸入A,B集合同原理 
                struct node* jiao = create(p->data);
                t->next = jiao;
                t = jiao;
                break;//因為找到了,所以break掉,去比較A的下一個元素 
            }
            q=q->next;//鏈表B的當前位置后移(q->next是下一個元素,讓q=下一個元素 
        }
        p=p->next;//鏈表A的當前位置后移(p->next是下一個元素,讓p=下一個元素 
    }
    /*
    輸出交集
    因為head_jiao->data頭節點的數據域中存的是-1(見上文定義交集頭結點 
    故從head_jiao的下一個開始
    */
    t=head_jiao->next;
    while(t!=NULL)//遍歷交集鏈表 
    {
        printf("%d ",t->data);//輸出元素,記得加空格 
        t=t->next;//后移 
    }
    //Attention:這個-1不應該被放在鏈表中 
    printf("-1\n");//最后的元素以-1結尾,記得加換行 
    
    /*
    並集思路:
    先復制A的所有元素在並集bing里面
    然后遍歷B,將B的每一個元素都與bing中元素比較
    若比較到最后都不一樣,則當前元素不在bing中
    將這個元素添加進bing的末尾 
    */
    
    p=head_a;//p是臨時變量,從A的頭開始
    t=head_bing;//t是臨時變量,用來存並集的鏈表
    while(p!=NULL)//遍歷鏈表A 
    {
        //以下操作與輸入A,B集合同理,使用鏈表A的數據 
        struct node* bing = create(p->data);
        t->next = bing;
        t = bing;
        p=p->next;//鏈表A的當前位置后移(p->next是下一個元素,讓p=下一個元素 
    }
    q=head_b;//q是臨時變量,從B的頭開始 

    while(q!=NULL)//遍歷鏈表B
    {
            h=head_bing;//h是臨時變量,讀取並集的鏈表
        int flag=0;//用flag來記錄是否有相同元素 
        while(h!=NULL)//遍歷並集
        {
            if(h->data==q->data)//存在相同元素
            { 
                flag=1;
                break;
            }
            h=h->next;//后移
        }
        if(!flag)//如果不存在相同元素
        {
            //以下操作與輸入A,B集合同理,使用鏈表B的當前元素數據 
            //t還是上面復制的時候定義的那個,繼續相同操作 
            struct node* bing = create(q->data);
            t->next = bing;
            t = bing;
        }
        q=q->next;//后移 
    }
    /*
    輸出並集
    因為head_bing->data頭節點的數據域中存的是-1(見上文定義並集頭結點 
    故從head_bing的下一個開始
    */ 
    t=head_bing->next;
    while(t!=NULL)//遍歷並集鏈表 
    {
        printf("%d ",t->data);//輸出元素,記得加空格 
        t=t->next;//后移 
    }
    //Attention:這個-1不應該被放在鏈表中 
    printf("-1\n");//最后的元素以-1結尾,記得加換行
    
    /*
    差集思路:
    同並集,先復制鏈表A在鏈表cha里面
    再遍歷鏈表bing,如果遇到元素在鏈表A中,則刪除鏈表節點
    */
    p=head_a;//p是臨時變量,從A的頭開始
    t=head_cha;//t是臨時變量,用來存差集的鏈表
    while(p!=NULL)//遍歷鏈表A 
    {
        //以下操作與輸入A,B集合同理,使用鏈表A的數據 
        struct node* cha = create(p->data);
        t->next = cha;
        t = cha;
        p=p->next;//鏈表A的當前位置后移(p->next是下一個元素,讓p=下一個元素 
    }

    q=head_jiao;//q是臨時變量,從jiao的頭開始
    while(q!=NULL)//遍歷鏈表jiao 
    {
        h=head_cha;//h是臨時變量,從cha的第1個開始 
        t=head_cha->next;//t是臨時變量,從cha的第2個開始 
        
        
        while(t!=NULL)//遍歷cha差集,尋找當前數,然后把它刪了 
        {
            if(t->data==q->data)//如果相等,刪除 
            {
                h->next=t->next;//跳過t指向下一個 
                break;
            }
            //如果沒刪除,后移 
            h=h->next;
            t=t->next;
        }
        q=q->next;//后移 
    }
    
    /*
    輸出差集
    因為head_cha->data頭節點的數據域中存的是-1(見上文定義並集頭結點 
    故從head_cha的下一個開始
    */ 
    t=head_cha->next;
    while(t!=NULL)//遍歷差集鏈表 
    {
        printf("%d ",t->data);//輸出元素,記得加空格 
        t=t->next;//后移 
    }
    //Attention:這個-1不應該被放在鏈表中 
    printf("-1\n");//最后的元素以-1結尾,記得加換行
    
    return 0;
}
代碼與解析

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM