回溯算法原理和几个常用的算法实例

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

回溯算法思想:

回溯(backtracking)是一种系统地搜索问题解答的方法。为了实现回溯,首先需要为问题定义一个解空间(solution space),这个空间必须至少包含问题的一个解(可能是最优的)。

下一步是组织解空间以便它能被容易地搜索。典型的组织方法是图(迷宫问题)或树(N皇后问题)。一旦定义了解空间的组织方法,这个空间即可按深度优先的方法从开始节点进行搜索。

回溯方法的步骤如下:

1) 定义一个解空间,它包含问题的解。

2) 用适于搜索的方式组织该空间。

3) 用深度优先法搜索该空间,利用限界函数避免移动到不可能产生解的子空间。

回溯算法的一个有趣的特性是在搜索执行的同时产生解空间。在搜索期间的任何时刻,仅保留从开始节点到当前节点的路径。因此,回溯算法的空间需求为O (从开始节点起最长路径的长度)。这个特性非常重要,因为解空间的大小通常是最长路径长度的指数或阶乘。所以如果要存储全部解空间的话,再多的空间也不够用。

算法应用:

回溯算法的求解过程实质上是一个先序遍历一棵"状态树"的过程,只是这棵树不是遍历前预先建立的,而是隐含在遍历过程中。

(1) 幂集问题(组合问题)(参见《数据结构》(严蔚敏))

求含N个元素的集合的幂集。

如对于集合A={1,2,3},则A的幂集为

p(A)={{1,2,3},{1,2},{1,3},{1},{2,3},{2},{3},Φ}

幂集的每个元素是一个集合,它或是空集,或含集合A中的一个元素,或含A 中的两个元素,或者等于集合A。反之,集合A中的每一个元素,它只有两种状态:属于幂集的元素集,或不属于幂集元素集。则求幂集P(A)的元素的过程可看成是依次对集合A中元素进行“取”或“舍”的过程,并且可以用一棵状态树来表示。求幂集元素的过程即为先序遍历这棵状态树的过程。

程序:

#include

#include

#define ERROR 0

#define OK 1

typedef int ElemType;

typedef struct LNode

{

ElemType data;

struct LNode *next;

} LNode,*LinkList;

//初始化

LinkList ListInit()

{

LNode *base=(LinkList)malloc(sizeof(LNode)); base->data=0;

base->next=NULL;

return base;

}

//插入一个元素

int ListInsert(LinkList L,int i,ElemType e)

{

LNode *p,*s;

int j=0;

p=(LNode *)L;

while(p&&j

{

p=p->next;

++j;

}

if(!p||j>i-1)

return ERROR;

s=(LNode *)malloc(sizeof(LNode));

s->data=e;

s->next=p->next;

p->next=s;

return OK;

}

//删除一个结点

int ListDelete(LinkList &L,int i,ElemType &e) {

LinkList p=L,q;

int j=0;

while(p->next&&j

{

p=p->next;

++j;

}

if(!(p->next)||j>i-1)

return ERROR;

q=p->next;

p->next=q->next;

e=q->data;

free(q);

}

//长度

int ListLength(LinkList L)

{

LinkList p=L;

int j=0;

if(!L)

return ERROR;

while(p->next)

{

p=p->next;

++j;

}

return j;

}

//查找一个元素

int GetElem(LinkList L,int i,ElemType &e) {

LNode *p=L;

int j=0;

while(p->next&&j

{

p=p->next;

++j;

}

if(!p||j>i)

return ERROR;

e=p->data;

return OK;

}

//输出链表元素

void Display(LinkList L)

{

LNode *p=L;

if(!(p->next))

{

printf("NULL,");

return;

}

else

p=p->next;

while(p)

{

printf("%d,",p->data);

p=p->next;

}

}

//求幂集

void PowerSet(int i,LinkList A,LinkList &B) {

int k=0;

ElemType e=0;

if(i>ListLength(A))

{

Display(B);

printf("\n");

}

else

{

GetElem(A,i,e);

k=ListLength(B);

ListInsert(B,k+1,e);

PowerSet(i+1,A,B);

ListDelete(B,k+1,e);

PowerSet(i+1,A,B);

}

}

int main()

{

LinkList list=ListInit(); //初始化

LinkList list2=ListInit();//初始化

ListInsert(list,1,1);//插入元素

相关文档
最新文档