最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語(yǔ)言中遞歸和排列組合詳解

 更新時(shí)間:2022年01月13日 10:08:04   作者:布布要成為最強(qiáng)的人  
大家好,本篇文章主要講的是C語(yǔ)言中遞歸和排列組合詳解,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽

排列組合三大問題:

1.打印n個(gè)數(shù)的全排列
2.打印n個(gè)數(shù)中任意m個(gè)數(shù)的全排列
3.打印n個(gè)數(shù)中任意m個(gè)數(shù)的組合

1.打印n個(gè)數(shù)的全排列

這個(gè)題實(shí)際上是可以直接用STL中的next_permutation()函數(shù),代碼如下:

#include<bits/stdc++.h>
using namespace std;
int main(){
	int data[4]={5,2,4,1};
	sort(data,data+4);//先排序得到字典序最小的序列
	do{
		for(int i=0;i<4;i++)
			cout<<data[i]<<" ";
		cout<<endl;
	}while(next_permutation(data,data+4));
}
這樣輸出出來的全排列是按照字典序輸出的,這是它的優(yōu)點(diǎn)。

如果用遞歸求全排列呢?
假如給了n個(gè)數(shù)123…n,求其全排列的數(shù)量,應(yīng)當(dāng)如何解決呢,下面給出一個(gè)遞歸的思路:

一開始先按照字典序排列,然后把第一個(gè)數(shù)依次和后面的數(shù)交換:
1 2 3 4 5…n
2 1 3 4 5…n
.
.
.
n 2 3 4 5…1
這是第一層遞歸,只要第一個(gè)數(shù)不同,不需要管后面n-1個(gè)數(shù)

然后在上面的每個(gè)數(shù)列中去掉第一個(gè)數(shù),對(duì)后面的n-1個(gè)數(shù)做如上操作,例如取第二組做該操作,則該第二層的遞歸為:
1 3 4 5…n
3 1 4 5…n
.
.
.
n 3 4 5…1

重復(fù)以上步驟,直到用完所有的數(shù)字。

這么講并不好理解,我從小規(guī)模到大規(guī)模來闡述這個(gè)思想:

假如只有兩個(gè)數(shù)1,2需要進(jìn)行全排列工作:
先按字典序排成1,2,這是第一層遞歸的第一組
把1去掉,只留下一個(gè)數(shù),那么只有1種情況。
第一層遞歸的第二組是2,1,這也是最后一組了
把2去掉,只留下一個(gè)數(shù),那么只有1種情況
因此兩個(gè)數(shù)的全排列是兩種情況

假如有三個(gè)數(shù)1,2,3需要進(jìn)行全排列工作:
直接看第一層遞歸的三種情況:
1、2、3;2、1、3;3、2、1
每一種情況都把第一個(gè)數(shù)去掉,就變成只有2個(gè)數(shù)的全排列了
而由上述所知,兩個(gè)數(shù)的全排列有兩種情況
那么第一層遞歸的三種情況都各自包含兩種情況即3×2=6

往后依舊借用前面的標(biāo)準(zhǔn)即可。
可是放到代碼實(shí)現(xiàn)的時(shí)候可不能做完一層刪一個(gè)數(shù),只能實(shí)現(xiàn)的了保留那層遞歸的第一個(gè)數(shù),然后繼續(xù)對(duì)下面的數(shù)做遞歸操作,這樣就完美符合了遞歸的思想。
代碼實(shí)現(xiàn)如下:

#include<bits/stdc++.h>
using namespace std;
#define Swap(a,b){int temp=a;a=b;b=temp;}
//也可以用STL的swap函數(shù),但是速度慢一些
int data[]={1,2,3,4,5};
int num=0;
void Perm(int begin,int end){
    if(begin==end)num++;//遞歸到底了,自然只有一種情況,num++
    else{
        for(int i=begin;i<=end;i++){
        	//i要注意從begin開始,自己和自己換的也算是一種情況
            Swap(data[begin],data[i]);
            Perm(begin+1,end);//保留第一個(gè)數(shù),進(jìn)入下一層遞歸
            Swap(data[begin],data[i]);//要記得換回來
        }
    }
}
int main(){
	Perm(0,4);
	cout<<num<<endl;
}

如果想要輸出這個(gè)排列,直接在Perm函數(shù)中的if語(yǔ)句下面做循環(huán)輸出即可。
需要注意的是:這樣輸出出來的并不一定符合字典序。

2.打印n個(gè)數(shù)中任意m個(gè)數(shù)的全排列

這個(gè)只需要把上面if語(yǔ)句中的條件改一下就行,改成begin==m即可
思路是一樣的,從小規(guī)模列起就好了。

3.打印n個(gè)數(shù)中任意m個(gè)數(shù)的組合

這個(gè)和上面的第2個(gè)問題就不一樣了,組合問題只需要選m個(gè)數(shù)而無(wú)須做排列,應(yīng)該怎么實(shí)現(xiàn)呢?
利用二進(jìn)制的思想,原理如下:
設(shè)一個(gè)集合{a0,a1,a2,…,an-1},子集共有2的n次方個(gè),其中包括空集。
例如一個(gè)n=3的集合{a0,a1,a2},其子集為{φ},{a0},{a1},{a1,a0},{a2},{a2,a0},{a2,a1},{a2,a1,a0}。為什么以這個(gè)順序來排呢?因?yàn)檫@樣非常符合二進(jìn)制位權(quán)值的思想。剛好可以和二進(jìn)制對(duì)應(yīng):

φa0a1a1 a0a2a2 a0a2 a1a2 a1 a0
000001010011100101110111

如何輸出這些子集?,還是利用二進(jìn)制位權(quán)的思想,利用相與運(yùn)算得出其二進(jìn)制數(shù)中的每一個(gè)1,直接對(duì)應(yīng)數(shù)字,完全代碼如下:

#include<bits/stdc++.h>
using namespace std;
void print_subset(int n){
    for(int i=0;i<(1<<n);i++){
        for(int j=0;j<n;j++)//打印子集,即打印i的二進(jìn)制數(shù)中的每一個(gè)1
            if(i&(1<<j))
                cout<<j<<" ";
        cout<<endl;
    }
}
int main(){
	int n;
	cin>>n;
	print_subset(n);
}

回到問題3,要找到任意m個(gè)數(shù)的組合,只需要做一個(gè)判斷:確定一個(gè)子集對(duì)應(yīng)的二進(jìn)制數(shù)中1的數(shù)量。這是解題的關(guān)鍵。
有一個(gè)很巧妙的做法:kk=kk&(kk-1)
重復(fù)使用該式子,直到kk為0,即可得出1的數(shù)量。

完整代碼如下:

#include<bits/stdc++.h>
using namespace std;
void print_subset(int n,int k){
    for(int i=0;i<(1<<n);i++){
        int num=0,kk=i;
        while(kk){
            kk=kk&(kk-1);
            num++;
        }
        if(num==k){
            for(int j=0;j<n;j++)//打印子集,即打印i的二進(jìn)制數(shù)中的每一個(gè)1
                if(i&(1<<j))
                    cout<<j<<" ";
            cout<<endl;
        }
    }
}
int main(){
	int n,k;
	cin>>n>>k;
	print_subset(n,k);
}

總結(jié)

到此這篇關(guān)于C語(yǔ)言中遞歸和排列組合詳解的文章就介紹到這了,更多相關(guān)C語(yǔ)言遞歸和排列組合內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • c++11 符號(hào)修飾與函數(shù)簽名、函數(shù)指針、匿名函數(shù)、仿函數(shù)、std::function與std::bind

    c++11 符號(hào)修飾與函數(shù)簽名、函數(shù)指針、匿名函數(shù)、仿函數(shù)、std::function與std::bind

    這篇文章主要介紹了c++11 符號(hào)修飾與函數(shù)簽名、函數(shù)指針、匿名函數(shù)、仿函數(shù)、std::function與std::bind,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-05-05
  • 利用C語(yǔ)言實(shí)現(xiàn)頁(yè)面置換算法的詳細(xì)過程

    利用C語(yǔ)言實(shí)現(xiàn)頁(yè)面置換算法的詳細(xì)過程

    一個(gè)好的頁(yè)面置換算法,應(yīng)具有較低的頁(yè)面更換頻率,從理論上講,應(yīng)該保留最近重復(fù)訪問的頁(yè)面,將以后都不再訪問或者很長(zhǎng)時(shí)間內(nèi)不再訪問的頁(yè)面調(diào)出,下面這篇文章主要給大家介紹了關(guān)于利用C語(yǔ)言實(shí)現(xiàn)頁(yè)面置換算法的相關(guān)資料,需要的朋友可以參考下
    2022-11-11
  • C++中AVL樹的底層以及實(shí)現(xiàn)方法總結(jié)

    C++中AVL樹的底層以及實(shí)現(xiàn)方法總結(jié)

    這篇文章主要介紹了C++中AVL樹的底層以及實(shí)現(xiàn)方法的相關(guān)資料,AVL樹是一種自平衡的二叉搜索樹,每個(gè)節(jié)點(diǎn)的左右子樹高度差不超過1,通過旋轉(zhuǎn)操作保持平衡,詳解了AVL樹的結(jié)構(gòu)、插入、旋轉(zhuǎn)、查找和遍歷方法,展示了其保持平衡的機(jī)制及對(duì)應(yīng)代碼實(shí)現(xiàn),需要的朋友可以參考下
    2024-10-10
  • C語(yǔ)言編程中統(tǒng)計(jì)輸入的行數(shù)以及單詞個(gè)數(shù)的方法

    C語(yǔ)言編程中統(tǒng)計(jì)輸入的行數(shù)以及單詞個(gè)數(shù)的方法

    這篇文章主要介紹了C語(yǔ)言編程中統(tǒng)計(jì)輸入的行數(shù)以及單詞個(gè)數(shù)的方法,利用最基礎(chǔ)的循環(huán)和判斷語(yǔ)句寫成,需要的朋友可以參考下
    2015-11-11
  • C++中實(shí)現(xiàn)調(diào)試日志輸出

    C++中實(shí)現(xiàn)調(diào)試日志輸出

    在?C++?編程中,調(diào)試日志對(duì)于定位問題和優(yōu)化代碼至關(guān)重要,本文將介紹幾種常用的調(diào)試日志輸出方法,并教你如何在日志中添加時(shí)間戳,希望對(duì)大家有所幫助
    2025-01-01
  • 使用ShellClass獲取文件屬性詳細(xì)信息的實(shí)現(xiàn)方法

    使用ShellClass獲取文件屬性詳細(xì)信息的實(shí)現(xiàn)方法

    本篇文章是對(duì)ShellClass獲取文件屬性詳細(xì)信息的實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • udp socket客戶端和udp服務(wù)端程序示例分享

    udp socket客戶端和udp服務(wù)端程序示例分享

    這篇文章主要介紹了udp socket客戶端和udp服務(wù)端程序示例,需要的朋友可以參考下
    2014-03-03
  • C++代碼實(shí)現(xiàn)逆波蘭式

    C++代碼實(shí)現(xiàn)逆波蘭式

    這篇文章主要為大家詳細(xì)介紹了C++代碼實(shí)現(xiàn)逆波蘭式,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • C++ VTK實(shí)例之高斯隨機(jī)數(shù)的生成

    C++ VTK實(shí)例之高斯隨機(jī)數(shù)的生成

    這篇文章主要介紹了VTK的一個(gè)實(shí)例之高斯隨機(jī)數(shù)的生成,本文演示了從一個(gè)平均數(shù)是0.0和標(biāo)準(zhǔn)偏差是2.2的高斯分布中隨機(jī)生成3個(gè)隨機(jī)數(shù)。感興趣的同學(xué)可以學(xué)習(xí)一下
    2021-11-11
  • C語(yǔ)言獲取文件長(zhǎng)度的方法

    C語(yǔ)言獲取文件長(zhǎng)度的方法

    這篇文章主要介紹了C語(yǔ)言獲取文件長(zhǎng)度的相關(guān)知識(shí),包括使用標(biāo)準(zhǔn)庫(kù)方法和使用Linux系統(tǒng)調(diào)用,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-10-10

最新評(píng)論

宜宾县| 吉林市| 清镇市| 东乡县| 桐梓县| 黄骅市| 吕梁市| 乌兰浩特市| 漳平市| 布拖县| 拜泉县| 略阳县| 平原县| 石狮市| 普陀区| 云安县| 玛多县| 中牟县| 富源县| 绥中县| 玉山县| 武安市| 沿河| 镇坪县| 理塘县| 合阳县| 盐源县| 客服| 徐汇区| 甘南县| 横峰县| 阿尔山市| 象州县| 鄂州市| 定安县| 临清市| 库尔勒市| 湛江市| 泽州县| 濉溪县| 平和县|