1.要理解回溯就必须清楚递归的定义和过程。
递归算法的非递归形式可采用回溯算法。主要考虑的问题在于:
- 怎样算完整的一轮操作。
- 执行的操作过程中怎样保存当前的状态以确保以后回溯访问。
- 怎样返回至上一次未执行的操作。
2.贴代码表现:
先序遍历二叉树:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "stackar.h" #include "fatal.h" char U[100]; typedef struct TreeNode { ElementType Element; struct TreeNode *Left; struct TreeNode *Right; } BTNode; BTNode *FindNode(BTNode *b,ElementType x) { //在二叉树中查找值为x的结点 BTNode *p; if (b==NULL) return NULL; else if (b->Element==x) return b; else { p=FindNode(b->Left,x); if (p!=NULL) return p; else return FindNode(b->Right,x); } } BTNode *CreateTree(BTNode *root) { //先序递归创建二叉树, //输入范例:abd#g##e##cf#h### //对应于: a(b(d(,g),e),c(f(,h),)) char ch; scanf("%c",&ch); if(ch=='#') { //printf("--%c$$$ ",ch); return NULL; } else { //printf("++%c*** ",ch); root=(BTNode *)malloc(sizeof(BTNode)); root->Element=ch; root->Left=CreateTree(root->Left); root->Right=CreateTree(root->Right); } return root; } int pd(BTNode *b) { if(b->Left==NULL&&b->Right==NULL) return 0; if(b->Left!=NULL&&b->Right==NULL) return 1; if(b->Left==NULL&&b->Right!=NULL) return 2; if(b->Left!=NULL&&b->Right!=NULL) return 3; } void prev(BTNode *b) { BTNode *f=b; int i,j; U[0]='|'; i=1; for(;;) { for(;;) { j=0; printf("%c",f->Element); switch(pd(f)) { case 0: { //当一个节点为叶子结点的时候开始回溯 j=1;break; } case 1:{ f=f->Left;break; //当一个节点有左孩子无右孩子的时候访问左孩子 } case 2:{ f=f->Right;break; //当一个节点有右孩子无左孩子的时候访问右孩子 } case 3:{ U[i++]=f->Element; //当一个节点有左孩子又有右孩子时存入节点的值 f=f->Left;break; //至字符数组U,以便以后回溯访问上一级。与此同时继续访问左孩子 } } if(j==1) break; } f=FindNode(b,U[i-1]); //根据U中最近保存的字符找出在原二叉树中相应的结点 if(--i==0) break; f=f->Right; //此时,应该访问回溯节点的右节点 //弹栈操作 } } void main() { BTNode *T,*p; T=CreateTree(p); prev(T); }