資料結構--C語言連結串列實現集合的(並,交,差)運算!(陣列)

2020-09-27 09:00:54

資料結構–C語言連結串列實現集合的(並,交,差)運算!(陣列)

效果如圖:
效果圖
要求:
從程式完善性上考慮,集合元素輸入時,要有檢查元素重複的功能,每個集合中不允許有重複的元素。集合可以用陣列也可以用連結串列儲存。
實現交、並、差運算時,分別把程式碼寫成函數的形式,即實現交運算的函數,實現並運算的函數,實現差運算的函數,在主函數中分別呼叫三個函數。
使用選單形式對應各個操作,應允許使用者反覆檢視結果,想結束程式時,輸入負數結束,使其編成一個完整的小軟體。選單參考範例如下:
1—輸入集合A和B
2—求集合A交B
3—求集合A並B
4—求集合A-B
退出,輸入一個負數!
驗收/測試用例:
輸入: A={1,2,3,4,5}
B={3,4,5,6,7}
要注意輸入的過程中,每輸入一個元素都要檢查輸入的這個元素是否和前面的元素重複,如果重複,要求使用者重新輸入當前元素。
驗收測試時要測試這種重複的情況。
輸出 A交B={3, 4, 5}
A並B={1,2,3,4,5,6,7}
A-B={1, 2}
程式碼部分

#include <stdio.h> 
int a[50]={0},b[50]={0},c[50]={0},d[50]={0},e[50]={0};

//顯示輸出
void show (){    
 printf("\t\t--------------集合運算--------------\n");
 printf("\n");
 printf("\t\t\t 1---輸入集合A和B\n");
 printf("\t\t\t 2---求集合A交B\n");
 printf("\t\t\t 3---求集合A並B\n");
 printf("\t\t\t 4---求集合A-B\n");
 printf("\t\t\t 退出,輸入一個負數!");
 printf("\n");
 printf("\t\t------------------------------------\n");
 printf("\n");
}

//輸入集合A和B 
void input(int x,int y){ 
 int i,j;
 printf("請輸入A的元素");
 for(i=0;i<x;i++){     
  scanf("%d",&a[i]);
  getchar();
  for(j=0;j<i;j++){    //通過迴圈判斷進行查重 
   if(a[i]==a[j]){    
    printf("輸入錯誤!請重新輸入");
    a[i]=0;
    i-- ;
   }
  }
 }  
 printf("請輸入B的元素");
 for(i=0;i<y;i++){     
  scanf("%d",&b[i]);
  getchar();
  for(j=0;j<i;j++){    //通過迴圈判斷進行查重 
   if(b[i]==b[j]){    
    printf("輸入錯誤!請重新輸入");
    b[i]=0; 
   }
  }
 } 
}

//求集合A交B,因為交集會多次使用,故與輸出分開。 
int hand(int x,int y){
 int i,j,k=0;
 for(i=0;i<x;i++){
  for(j=0;j<y;j++){
   if(a[i]==b[j]){
    c[k]=a[i];
    k++;
   }
  }
 }
 return k;
} 

//輸出交集
void outhand(int k){
 int i;
 printf("A交B={");
 for(i=0;i<k-1;i++){
  printf("\t %d,",c[i]);
 } 
 printf("\t %d}\n",c[k-1]);
} 

//求集合A並B
void combine(int x,int y,int k){
 int i,j,m=0,n;
 int com[50]={0}; 
 for(i=0;i<x;i++){
  d[m]=a[i];
  m++;
 }
 for(i=0;i<y;i++){
  d[m]=b[i];
  m++;   //m為a和b集合的總的元素個數 
 }
 /*
 for(i=0;i<x+y-k;i++){    //x+y-k為並集的實際元素個數 ,且該回圈除去重複元素 
  for(j=m;j>i;j--){
   if(d[j]==d[i]){
    d[j]=d[j+1]; //用重複元素後一位元素覆蓋該元素 
    i--;   //從新進行該輪迴圈,消除上一步帶來的多個元素重複的影響 
    break;   //跳出裡層for迴圈 
   }
  }
 }
 */
 for(i=0;i<x+y-k;i++){    //x+y-k為並集的實際元素個數 ,且該回圈除去重複元素 
  for(j=i+1;j<m;j++){
   if(d[j]==d[i]){
    for(n=j;n<m;n++){
     d[n]=d[n+1];
    }
    break;
   }
  }
 }
 printf("A並B={");
 for(i=0;i<x+y-k-1;i++){
  printf("\t %d,",d[i]);
 } 
 printf("\t %d}\n",d[x+y-k-1]);
}

//求集合A-B 
void reduce(int x,int k){
 int i,j,m;
 for(i=0;i<x;i++){
  e[i]=a[i];
 }
 for(i=0;i<x-k;i++){  //思路同並集中除去重複元素 
  for(j=0;j<k;j++){
   if(e[i]==c[j]){
    for (m=i;m<x;m++){  //將重複後所有元素前移 
     e[m]=e[m+1]; 
    }
    i--;
    break;
   }
  }
 }
 printf("A-B={");
 for(i=0;i<x-k-1;i++){
  printf("\t %d,",e[i]);
 } 
 printf("\t %d}\n",e[x-k-1]);
}

int main(){
 int x,y,i,j,k,choice;
 while(1){
  show();
  printf("請選擇你需要進行的操作\n");
  scanf("%d",&choice);
  if(choice<0){
   printf("已退出。");
   return 0;
  }else{
   switch(choice){
    case 1:
     printf("請輸入A集合中元素個數\n");
     scanf("%d",&x);
     printf("請輸入B集合中元素個數\n");
     scanf("%d",&y);
     input(x,y);
     k=hand(x,y);
     printf("請按回車繼續!\n");
     getchar();
     system("cls");
     break;
    case 2:
     outhand(k);
     printf("請按回車繼續!\n");
     getchar();
     getchar();
     system("cls");
     break;
    case 3:
     combine(x,y,k);
     printf("請按回車繼續!\n");
     getchar();
     getchar();
     system("cls");
     break;
    case 4:
     reduce(x,k);
     printf("請按回車繼續!\n");
     getchar();
     getchar();
     system("cls");
     break;
    default :
     printf("輸入有誤!\n");
     printf("請按回車繼續!\n");
     getchar();
     getchar();
     system("cls");
     break;
   }
  }
 }
 return 0;
}

該程式碼只是運用普通陣列實現,未運用到動態陣列或連結串列,因此若集合元素超過50則無法使用,(其實這個題更適合用連結串列做,畢竟連結串列更容易進行刪除。)歡迎各位大佬指正,後續會寫用連結串列實現的程式碼,寫好後會在下面附加連結。