1. 程式人生 > >子集樹和排列樹

子集樹和排列樹

子集樹

當所給的問題是從n個元素的集合S中找出滿足某種性質的子集時,相應的解空間稱為子集樹。
比如,01揹包問題就是子集樹。這類問題通常有2^n個葉子節點,總節點個數是2^(n+1)-1。遍歷子集樹的任何演算法都需要 O(2^n)的時間。

選取數字:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


void sel(int *arr, int len, int *ass, int index)
{
    if (index == len)
    {
        for
(int i = 0; i < len; ++i) { if (ass[i]) { printf("%d ", arr[i]); } } printf("\n"); } else { ass[index] = 1; sel(arr, len, ass, index+1); ass[index] = 0; sel(arr, len, ass, index+1
); } } int main() { int arr[] = {1,3,5}; int len = sizeof(arr)/sizeof(int); int *ass = (int*)malloc(len * sizeof(int)); if (ass) { sel(arr, len, ass, 0); free(ass); } return 0; }

 

排列樹

當所給問題是確定n個元素滿足某種性質的排列時,相應的解空間樹稱為排列樹。

排列樹通常有n!個葉子節點。因此遍歷排列樹需要O(n!)的計算時間

 

陣列全排列:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


void swap(int *a, int *b)
{
    int tmp = *a;
    *a = *b;
    *b = tmp;
}


void permutation(int *arr, int len, int index)
{
    if (index == len)
    {
        for (int i = 0; i < len; ++i)
        {
            printf("%d ", arr[i]);
        }
        printf("\n");
    }
    else
    {
        for (int i = index; i < len; ++i)
        {
            swap(&arr[index], &arr[i]);
            permutation(arr, len, index+1);
            swap(&arr[index], &arr[i]);
        }
    }
}


int main()
{
    int arr[] = {1,2,3};
    int len = sizeof(arr)/sizeof(int);

    permutation(arr, len, 0);

    return 0;
}