列舉子集的三種方法 紫書

2022-05-28 13:57:13 字數 2672 閱讀 8510

之前一直沒怎麼重視這一塊,理解也是半知半解,現在想想還是得好好記下。

一.增量構造法

什麼意思呢,簡單來說就是把乙個乙個元素放進去又拿出來的過程

先上**

//ass集合的陣列

//num子集的陣列

//n 集合的元素的個數

//cur 初始為0,代表著子集的元素的個數

void print_subset(int n, int *num, int

cur)

cout

<

int st = cur ? num[cur - 1]+1 : 0;//

選擇最小的未被選擇的集合的乙個元素

for (int i = st; i < n; i++)

}

下面借用一張圖,思路很清晰

注意:這裡的1 2 3 4表示的是集合的下標,不是元素的值

跟著演算法的思路走一遍:

一開始,我們的子集為空,所以不需要輸出,然後我們現在的子集元素個數cur為0,然後 我們拿   目前的  未被用到的  最小號元素放進去  子集,

ok,目前的狀態是子集裡面已經有了0號元素,保持這個狀態我們接著往下走,

現在,我們的子集裡面已經有了0號元素,可以輸出0號,目前我們的子集元素個數cur為1,然後我們拿   目前的  未被用到的  最小號元素放進去  子集

ok,目前的狀態是子集裡面有了1號元素,保持這個狀態我們接著往下走

………………………………以此類推,直到遇到第乙個邊界,也就是num[cur]==3 的時候,我們的集合的元素的個數只有4個,所以輸出目前的子集後我們直接返回走,

目前我們回到了num[cur==2 ]=2的狀態,開始進入下乙個迴圈,

ok,此時我們的num[cur==2]=3,也就是說本來num[2]==2此時被代替成了3,這樣子目前  子集就是  0 1 3,以此類推

這樣我們的結果就是

0 10 1 2

0 1 2 3

0 1 3

0 20 2 3

0 31 2

1 2 3

1 32 3

二.位向量法

其實就是 放和不放 所得到的各種情況

例如 我目前的 集合的元素為 1 2 3 4 5

那我先拿出第乙個元素  1

那我的子集要不要這個元素呢?有要和不要兩種情況

那目前就有了兩個子集  :   第乙個子集 為   空

第二個子集 為   1

再拿出第二個元素  2:

那我的子集要不要這個元素呢?有要和不要兩種情況,而第乙個元素 1 要和不要也有兩種情況,於是目前就有了四種情況

那目前就有了四個子集:   第乙個子集為空

第二個子集為 1

第三個子集為 2

第四個子集為 1 2

以此類推,我們就會得到所有子集的情況

下面給出**:

#includeusing

namespace

std;

//ass集合的元素

//num子集的陣列

//n 集合的元素的個數

//cur 初始為0,代表著集合元素的下標

void print_subset(int n, int *num, int

cur)

}cout

<

return

; }

num[cur] = 1;//

要ass[cur]這個元素

print_subset(n, num, cur + 1

); num[cur] = 0;//

不要ass[cur]這個元素

print_subset(n, num, cur + 1

);}

三  . 二進位制法

這個應該是最難懂的,需要先學習二進位制的概念和各種位運算子,不然沒必要往下看

如果你已經懂了,那接著往下說。

要知道,二進位制中,只有 1 和 0 兩個數字,那我們就把 1代表有這個元素,0代表沒有這個元素

假如我們的集合為

那麼子集用二進位制表示就是這樣

001 010 011 100 101 110 111 如此,我們知道有9種情況

這代表著什麼呢?

(它的代表是反向的)

例如 001代表著 有 7 這個元素 ,沒有 8 和 9 元素 ,

101代表著 有7和 9元素,沒有 8元素

1 1 1 代表著全部都有

那好,我們知道它是怎麼代表的,那又有什麼用呢?

接著往下看:

首先我們要知道集合元素的個數,這裡假設為 n

那我們再看這樣乙個式子    (1什麼意思呢?我們知道陣列是從0開始的,比如我們的集合有3個元素,放在陣列裡面,它們的下標就是 0 1 2

那麼我們可以知道n==3,所以我們  (1那麼我們接下來不斷的讓 111 減去 001也就是 十進位制的 1 ,那麼就有了   110   101  011  010 001  000

所以,下面給出列舉的**:

//

ass集合的元素

//n 集合的元素的個數

void print_subset(int n,int *ass)

}cout

<

}

列舉子集的幾種方法

程式設計挑戰競賽上156頁說了列舉組合和子集的幾種方法,我覺得挺好的,收藏一下 都是利用二進位制數的模型來進行列舉子集或者組合 下面列舉集合都是在二進位制位上進行列舉。列舉k個數的子集 void eunmset int k 用k個二進位制位數列舉k個狀態 當k等於3時,即eunmset 3 輸出 0...

構造子集的三種方法

包含空集 來自紫書 的所有子集 增量構造法 rujia liu include pragma warning disable 4996 using namespace std void print subset int n,int a,int cur int a 10 int main 的所有子集 ...

三種方法 2020 11 23

利用連線類,例項化得到連線物件 連線類 連線物件 new 連線類 cmd.executescalar cmd.excutereader 關注其中一條資料 物件名.read 獲取關注列所對應的值 console.writeline 物件名 name while 物件名.read 功能,聚焦下一行資料。...