1. 程式人生 > >C語言實現集合的交,並,差

C語言實現集合的交,並,差

【問題描述】
        編制一個能演示執行集合的並、交和差運算的程式
【基本要求】
       (1)集合的元素限定為小寫字母字元[ 'a'......'z' ]
       (2 )演示程式以使用者和計算機對話的方式執行
【測試資料】

【實現提示】
          以有序連結串列表示集合
【程式碼過程】
    1。先定義 集合的資料型別 notes.h  
         

//notes.h
typedef struct LNode...{
    ElemType    data;
    LNode        *next;
}*Link, *Position;

typedef struct...{
    Link    head,tail;
    int        len;
}LinkSet;
   //~
    2。以後要用的一些常量放在   constValues.h
       #include<stdio.h>
#include <malloc.h>
#include <stdlib.h>
//函式結果狀態程式碼
#define    TRUE    1
#define    FALSE    0
#define    OK        1
#define    ERROR    0
#define    INFEASIBLE    -1
#define OVERFLOW    -2   

#define ElemType        int        //存放資料的型別

typedef int    Status;                //函式的返回值
   //~
    3。集合實現函式   setsFun.h

/**//****************** 函式定義 *********************/
Status InitSets(LinkSet &ls)...{   
    //初始化 集合
    ls.head = (Link) malloc( sizeof(Link));
    ls.tail = (Link) malloc( sizeof(Link));   
    if(!ls.head || !ls.tail) exit(OVERFLOW);    //如果分配失敗

    ls.head->next = ls.tail->next =    NULL;        //頭、尾指標為空
    ls.len = 0;                                    //長度為0   
    return OK;
}

Status CreateNode(Link &link,ElemType e)...{
    //建立一節點,內容為e
    link = (Link) malloc( sizeof(Link));
    if(!link)    exit(OVERFLOW);   
    link->data = e;                                //值設定
    link->next = NULL;                            //指向空
    return OK;
}

Position PriorInsertNode(LinkSet &ls,Link &link)...{
    //找出節點link要插入到ls的前一個節點
    if(!ls.head->next) return ls.head;
    Link h1 = ls.head->next, h2 = h1->next;            //h1:前一節點,h2:前一節點的後一節點
    if(link->data < h1->data) return ls.head;        //如果比第一個節點小,返回頭指標
    while(h1 && h2)...{
        if(h1->data < (link->data) && h2->data > (link->data) )    //如果>h1  && <h2,說明找到插入的地方了
            break;
        if(h1->data == (link->data) || h2->data ==(link->data) )
            return NULL;                            //如果重複,返回NULL
        else                                        //否則,順次往後挪一個節點
            h1=h2,h2=h1->next;
    }
    return h1;
}

Status Append(LinkSet &ls, Link &link)...{
    //向集合末尾追加節點
    if(ls.head->next == NULL)    ls.head->next = link;
    else ls.tail->next->next = link;
    ls.tail->next = link;
    ls.len ++;
    return OK;
}

Status InsertNode(LinkSet &ls, Link &link)...{
    //向集合中插入節點
    Position p = PriorInsertNode(ls,link);
    if(!p)    return ERROR;                        //如果集合中已有相應元素
    link->next = p->next;
    if(!p->next)    ls.tail->next = link;        //如果前一節點為尾節點,修改tail
    p->next = link;   
    ls.len++;
    return OK;
}

Position PriorNode(LinkSet &ls, Link &link)...{
    //返回集合中 該節點的前一節點,不存在返回NULL
    int j=0;
    Link pre,h = ls.head;
    while(h->next && j<=ls.len && h!=link)...{
        pre = h; h=h->next; j++;
    }
    if(j==0)    return    NULL;
    return pre;
}

Status PrintSets(LinkSet &ls)...{
    //列印集合
    Link h=ls.head->next;
    printf("[ ");
    while(h)...{
        printf("%c ",h->data);
        h = h->next;
    }
    printf(" ] ");
    return OK;
}

Position GetHead(LinkSet &ls)...{
    //獲得集合的頭節點
    return ls.head;
}

Position NextPos(Link &link)...{
    //獲得當前節點的下一個節點
    return link?link->next:link;
}

Status Empty(LinkSet &ls)...{
    //空為真
    return ls.head->next==NULL;
}

ElemType GetCurElem(Link &link)...{
    //獲得當前節點的資料
    return link->data;
}

int Compare(Link &la, Link &lb)...{
    //判斷兩個節點的大小
    return la->data - lb->data;
}

int Compare(ElemType e1, ElemType e2)...{
    //比較兩個數字的大小
    return e1-e2;   
}

Status DelFirst(LinkSet &ls,Link &q)...{
    //已知h為線性連結串列的頭節點,刪除表中的第一個節點,並以q返回
    Link h = ls.head;
    if(!h->next) return ERROR;
    q = h->next;   
    h->next = h->next->next;
    q->next=NULL;   
    ls.len--;
    return OK;
}

Status FreeNode(Link &l)...{//釋放節點,有問題
    free(l);
    return OK;
}

Status UnionSets(LinkSet lsa, LinkSet &lsb, LinkSet &lsc)...{
    //已知集合ls1,ls2的元素按值非遞減排列
    //將集合ls1,ls2的並集到ls3
    if( !InitSets(lsc) ) return ERROR;
    Link node;
    Link ha = lsa.head, hb=lsb.head;            //找到兩節點的頭指標
    Link pa = NextPos(ha), pb = NextPos(hb);
    while( !Empty(lsa) && !Empty(lsb) )...{       
        int result = Compare(pa,pb);            //比較兩節點大小
        if(  result<0) ...{
            DelFirst(lsa,node);Append(lsc,node); pa = NextPos(ha);        //向lsc插入lsa的相關節點   
        }else if(result>0)...{                                                //向lsc插入lsb的相關節點
            DelFirst(lsb,node);Append(lsc,node); pb = NextPos(hb);   
        }else...{                                   
            DelFirst(lsb,node); pb = NextPos(hb);//如果兩 節點相同,刪除lsb中重複的節點,即以lsa為標準
        }
    }
    while(!Empty(lsa))...{           
        DelFirst(lsa,node);Append(lsc,node);
    }
    while(!Empty(lsb))...{
        DelFirst(lsb,node);Append(lsc,node);
    }
    return OK;
}

Status IntersectionSets(LinkSet &lsa,LinkSet &lsb, LinkSet &lsc)...{
    //已知集合ls1,ls2的元素按值非遞減排列
    //將集合ls1,ls2的交集到ls3
    if( !InitSets(lsc) ) return ERROR;
    Link node;
    Link ha = lsa.head, hb=lsb.head;
    Link pa = NextPos(ha), pb = NextPos(hb);
    while( !Empty(lsa) && !Empty(lsb) )...{
        int result = Compare(pa,pb);
        if(  result<0) ...{
            DelFirst(lsa,node);pa = NextPos(ha);           
        }else if(result>0)...{
            DelFirst(lsb,node); pb = NextPos(hb);   
        }else...{
            DelFirst(lsb,node); Append(lsc,node);pb = NextPos(hb);
            DelFirst(lsa,node);pa = NextPos(ha);
        }
    }
    while(!Empty(lsa))...{
        DelFirst(lsa,node);Append(lsc,node);
    }
    return OK;
}

Status DifferenceSets(LinkSet &lsa,LinkSet &lsb, LinkSet &lsc)...{
    //已知集合ls1,ls2的元素按值非遞減排列
    //ls3 = ls1 - ls2
    if( !InitSets(lsc) ) return ERROR;
    Link node;
    Link ha = lsa.head, hb=lsb.head;
    Link pa = NextPos(ha), pb = NextPos(hb);//,pb2 = NextPos(pb1);
    while( !Empty(lsa) && !Empty(lsb) )...{
        int result = Compare(pa,pb);
        if(  result<0) ...{
            DelFirst(lsa,node);Append(lsc,node);pa = NextPos(ha);           
        }else if(result>0)...{
            DelFirst(lsb,node); pb = NextPos(hb);   
        }else...{
            DelFirst(lsa,node); pa = NextPos(ha);
            DelFirst(lsb,node); pb = NextPos(hb);           
        }
    }
    return OK;
}

Status CopySets(LinkSet lsa, LinkSet lsb)...{
    //將集合lsa拷貝到lsb中
    InitSets(lsb);
    Link la = lsa.head->next, lb = lsb.head->next;
    while(la)...{
        Link node;
        CreateNode(node,la->data);
        lb=node;
        lsb.len++;

        la = la->next;
        lb = lb->next;
    }
    lsb.tail = lb;
    return OK;
}
//~    4。測試 test.cpp
#include "constValues.h"        //常量頭 檔案
#include "notes.h"                //節點定義 標頭檔案
#include "setsFun.h"            //集合操作函式 標頭檔案

/**//**************** 測試 ***********************************/
void Initialization()...{
    printf("**************************************************************************** "    );
    printf("*MakeSet1-1     MakeSet1-2  Union-u  Intersection-i  Difference-d  Quit-q * "    );
    printf("**************************************************************************** "    );
}


void main()
...{   
    LinkSet set1,set2,set3,seta,setb;
    InitSets(set1),InitSets(set2);        //初始化集合
    while(1)...{
        Initialization();               
        printf("集合Set1:");
        PrintSets(set1);                //列印集合set1
        printf("集合Set2:");
        PrintSets(set2);                //列印集合set1
        printf("請鍵入操作程式碼:");
        fflush(stdin);        //清空緩衝區
        char oper = getchar();
        char setsContent[200];
        switch(oper)
        ...{
        case '1':                        //集合set1 賦值
            printf("請輸入集合Set1的內容:");
            fflush(stdin);
            gets(setsContent);           
            InitSets(set1);
            SetSets(set1,setsContent);           
            break;
        case '2':                        //集合set1 賦值
            printf("請輸入集合Set1的內容:");
            fflush(stdin);
            gets(setsContent);
            InitSets(set2);
            SetSets(set2,setsContent);
            break;
        case 'u':
        case 'U':                        //求並       
            InitSets(set3);           
            CopySets(set1,seta);        //因為求並的演算法是新增一個節點,刪除set1,set2中對應的節點,   
            CopySets(set2,setb);        //所以要複製一份
            UnionSets(seta,setb,set3);    //下同       
            printf("set1 U set2=: ");
            PrintSets(set3);
            fflush(stdin);
            getchar();
            break;
        case 'i':
        case 'I':                        //求交   
            InitSets(set3);       
            CopySets(set1,seta);               
            CopySets(set2,setb);
            IntersectionSets(seta,setb,set3);
            printf("set1 交 set2=: ");
            PrintSets(set3);
            fflush(stdin);
            getchar();
            break;
        case 'd':
        case 'D':                        //求差
            InitSets(set3);       
            CopySets(set1,seta);           
            CopySets(set2,setb);
            DifferenceSets(seta,setb,set3);
            printf("set1 - set2=: ");
            PrintSets(set3);
            fflush(stdin);
            getchar();
            break;           
        case 'q':
        case 'Q':
            exit(0);
            break;
        }
        system("cls");    //清屏
    }
}