码迷,mamicode.com
首页 > 其他好文 > 详细

看数据结构写代码(33) 树与回溯法(一) 子集树

时间:2015-04-01 15:32:10      阅读:269      评论:0      收藏:0      [点我收藏+]

标签:回溯法   树与回溯法   

回溯法 是 一种 在 穷举 中,裁剪 不满足 条件 的 分支,已达到 提高 效率的 方法。其基本原型 是 树的 先序遍历,从 树根 到 树叶的路径 是 问题的 一个 解。 

回溯法的基本框架 =  确定 解空间 + 深度优先遍历 + 裁剪函数 + 确定结果函数

其中 解空间,分为 子集树 和 排序树。

具体 概念 详解:参考 点击打开链接  和 点击打开链接

递归算法通用 模板如下:

回溯法对解空间作深度优先搜索,因此,在一般情况下用递归方法实现回溯法。

// 针对N叉树的递归回溯方法

void backtrack (int t)

{

    if (t > n) {

       // 到达叶子结点,将结果输出

       output (x);

    }

    else {

       // 遍历结点t的所有子结点

       for (int i = f(n,t); i <= g(n,t); i ++ ) {

           x[t] = h[i];

           // 如果不满足剪枝条件,则继续遍历

           if (constraint (t) && bound (t)) 

              backtrack (t + 1);

       }

    }

}

下面的 三个例子 都是 根据 这个 模板 来 写的。

// Backtrack.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <cstring>
#define SET_MAX_SIZE 1000
static bool set[SET_MAX_SIZE];

//获得幂集
//times 表示 当前递归层的层数,从0 层开始
//n 表示 集合的数量
void getPowset(int times,int n){
	if (times >= n)
	{
		for (int i = 0; i < n; i++)
		{
			if (set[i] == true)
			{
				printf("%d\t",i+1);
			}
		}
		printf("\n");
	}
	else
	{
		for (int i = 0; i < 2; i++)
		{
			set[times] = i;getPowset(times+1,n);
		}
	}
}

//打印string的所有子串
//times表示当前 递归层数
void getAllSubChar(int times,char * string){
	int len = strlen(string);
	if (times >= len)
	{
		for (int i = 0; i < len; i++)
		{
			if (set[i] == true)
			{
				printf("%c\t",string[i]);
			}
		}
		printf("\n");
	}
	else{
		for (int i = 0; i < 2; i++)
		{
			set[times] = i;getAllSubChar(times+1,string);
		}
	}
}

//打印集合中所有等于 N 的组合.
void getAllEqual(int times,int arrayLen,int * array,int equal){
	int len = arrayLen;
	if (times >= len)
	{
		int sum = 0;
		for (int i = 0; i < len; i++)
		{
			if (set[i] == true)
			{
				sum += array[i];
			}
		}
		if (sum == equal)
		{
			for (int i = 0; i < len; i++)
			{
				if (set[i] == true)
				{
					printf("%d\t",array[i]);
				}
			}
			printf("\n");
		}
	}
	else
	{
		for (int i = 0; i < 2; i++)
		{
			set[times] = i;
			int sum = 0;
			//裁剪..剪掉 不符合的条件.
			for (int i = 0; i <= times; i++)
			{
				if (set[i]== true)
				{
					sum += array[i];
				}
			}
			if (sum <= equal)
			{
				getAllEqual(times+1,arrayLen,array,equal);
			}
		}
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	printf("1~ N 的幂集,请输入N值:");
	int n;
	scanf("%d",&n);
	printf("1~%d的幂集为:\n",n);
	getPowset(0,n);
	char string[SET_MAX_SIZE];
	printf("请输入字符串的:");
	scanf("%s",string);
	printf("%s的所有子字符串如下:\n",string);
	getAllSubChar(0,string);
	printf("查找集合(3,2,5,6,7,8,10,20,4,15)中 等于 10的 组合\n");
	int array[] = {3,2,5,6,7,8,10,20,4,15};
	getAllEqual(0,sizeof(array)/sizeof(int),array,10);
	return 0;
}
技术分享


看数据结构写代码(33) 树与回溯法(一) 子集树

标签:回溯法   树与回溯法   

原文地址:http://blog.csdn.net/fuming0210sc/article/details/44805693

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!