/* m元素集合的n個元素子集 說明: 假設有個集合擁有m個元素,任意的從集合中取出n個元素,則這n個元素所形成的可能子集有那些? 解法: 假設有5個元素的集點,取出3個元素的可能子集如下: {1 2 3} 、{1 2 4 } 、{1 2 5} 、{1 3 4} 、{1 3 5} 、{1 4 5} ... ...
/* m元素集合的n個元素子集 說明: 假設有個集合擁有m個元素,任意的從集合中取出n個元素,則這n個元素所形成的可能子集有那些? 解法: 假設有5個元素的集點,取出3個元素的可能子集如下: {1 2 3} 、{1 2 4 } 、{1 2 5} 、{1 3 4} 、{1 3 5} 、{1 4 5} 、{2 3 4} 、{2 3 5} 、{2 4 5} 、{3 4 5}這些子集已經使用字 典順序排列,如此才可以觀察出一些規則: 如果最右一個元素小於m,則如同碼表一樣的不斷加 1 如果右邊一位已至最大值,則加1的位置往左移 每次加1的位置往左移後,必須重新調整右邊的元素為遞減順序 所以關鍵點就在於哪一個位置必須進行加1的動作,到底是最右一個位置要加1? 還是其它的位置?在實際撰寫程式時,可以使用一個變數positon來記錄加1的位置,position的初值設定為n-1 ,因為我們要使用陣 列,而最右邊的索引值為最大 的n-1,在position位置的值若小於m就不斷加1,如果大於m 了, position就減1,也就是往左移一個 位置;由於位置左移後,右邊的元素會 經過調整,所以我們必須檢查最右邊的元素是否小於m,如果是,則position調整回n-1,如 果不是,則positon維持不變。 */ #include<stdio.h> #include<stdlib.h> #define MAX 20 int main(void) { int set[MAX]; int m, n, position; int i; printf("輸入集合數: "); scanf("%d", &m); printf("輸入取出元素 n:"); scanf("%d", &n); for(i = 0; i < n; i++) { set[i] = i + 1; } for(i = 0; i < n; i++) { printf("%d", set[i]); } putchar('\n'); position = n - 1; while(1) { if(set[n - 1] == m) { position--; } else { position = n - 1; } set[position]++; for(i = position + 1; i < n; i++) { set[i] = set[i - 1] + 1; } for(i = 0; i < n; i++) { printf("%d", set[i]); } putchar('\n'); if(set[0] >= m - n + 1) { break; } } return 0; }