日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

回溯法经典算法 求集合中所有的子集

發布時間:2023/12/14 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 回溯法经典算法 求集合中所有的子集 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

今天我們來看一下子集的問題。

題目描述:給定一個任意集合A,集合的長度為Length,讓你打印出這個集合中所包含的所有子集。

題目分析:此問題實際上也是一個遍歷樹的問題,進行遍歷每一個子元素,再進入下層函數時候記錄上層結果,加入到下層函數中,再存儲起來。其實總結器來他就是一顆完全二叉樹。以下我們結合圖來具體的說一下:

我們以集合{1,2,3}來對此畫樹狀圖理解一下。圖如下:

以此我們可以得到集合{1,2,3}中的子集有{},{1},{2},{3},{1,2},{1,3},{2,3},{1,2,3};

以此我們就可以用遞歸算法對其進行代碼操作。

具體的遞歸方法:對于一個含有n個元素的集合,我們要對其進行找子集,首先我們需要先定義一個數組,以此來存儲對這N位的2進制數來表示這個集合,第i為如果為1則表示第i個元素在表示的這個集合中,否則則不再這個集合中。簡單的來說就是首先我們先讓這個數組的第一個元素為No,然后他會一直往下找,如果到遞歸結束時還是No,就將它打印出來,然后進行回溯到上一層。然后我們就把這個元素定位Yes,然后在進行在Yes條件下進行遞歸尋找,我們每次進行到遞歸結束的條件時,我們對其進行回溯。可能我說的還是有點理解不了,大家可以結合著上面的圖來看代碼:

#include<stdio.h> #include<string.h> #include<assert.h>int arr[]={0};//存儲當前第i個位置元素包含還是不包含 void Ziji(char brr[],int k,int length)//k是遞歸的層次,k與集合的長度有關 {assert(arr!=NULL); if(k==length)//遞歸結束的條件{printf("{ ");for(int i=0;i<length;i++){if(arr[i]==1){printf("%c ",brr[i]);}}printf("}");printf("\n"); }else{arr[k]=0;//集合中的第i個元素沒有包含,也就是(No)Ziji(brr,k+1,length); //進行沒有被包含(No)的遞歸arr[k]=1;//集合中的第i個元素被包含(Yes)Ziji(brr,k+1,length);//然后進行被包含下(Yes)的遞歸} } int main() {char str[]="ABC";int lenth=strlen(str);Ziji(str,0,lenth);return 0; }

?綜上所述呢,我們可以得到一個含有N個元素的集合,它的所有子集的個數為N!個。

?大家現在結合著代碼是不是理解了此算法的遞歸操作呢?

如果沒理解我再給大家講一下非遞歸的算法,我覺得這種辦法挺好運的,這種辦法就是用C++中的位運算符來進行操作的,上面我們可以得出一個含有N個元素的集合,它的所有子集的個數為N!個,于是我們對其進行移位操作。

如集合A={a,b,c},其子集個數為8;對于任意一個元素,在每個子集中,

要么存在,要么不存在,對應關系是:

a->1或a->0

b->1或b->0

c->1或c->0

映射為子集:

(a,b,c)

(1,1,1)->(a,b,c)

(1,1,0)->(a,b ? )

(1,0,1)->(a, ? c)

(1,0,0)->(a ? ? ?)

(0,1,1)->( ? b,c)

(0,1,0)->( ? b ? )

(0,0,1)->( ? ? ?c)

根據以上規律我們可以得出拿一個整形值與一個數進行&操作可以得到我們所需要的子集。進行再一步的觀察我們可以看出這個數就是1,每次進行&之后,讓這個數進行左移(<<)i位,這個i的初始為0,結束為N,所以我們就可以求出我們所需要的結果,具體代碼如下:

#include<stdio.h> #include<assert.h> #include<string.h> int main() {char arr[]="ABC";int a=strlen(arr);int thm=1<<a;//含有N個元素的子集共有N!個for(int i=0;i<thm;i++){for(int j=0;j<a;j++)if(i&1<<j)//每次要對其進行左移操作,然后又i進行&{printf("%c",arr[j]); }printf("\n");}return 0; }

以上的內容就是我對一個集合中求子集問題的所有理解,希望它可以幫助大家。如有錯誤,請大家評論指正。

?


?

?

總結

以上是生活随笔為你收集整理的回溯法经典算法 求集合中所有的子集的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。