递归数算法
⑴ C语言二叉树递归算法怎么做
#include<stdio.h>
#include<string.h>
structtreenode{
intvalue;
treenode*left;
treenode*right;
};
typedeftreenode*BiTree;
voidvisit(treenode*node)
{
printf("%2d",node->value);
}
//结点总数
intnode(BiTreeT)
{
if(!T){
return0;
}
returnnode(T->left)+node(T->right)+1;
}
//前序
voidpreOrder(BiTreeT)
{
if(T){
visit(T);
preOrder(T->left);
preOrder(T->right);
}
}
//中序
voidinOrder(BiTreeT)
{
if(T){
inOrder(T->left);
visit(T);
inOrder(T->right);
}
}
//后序
voidpostOrder(BiTreeT)
{
if(T){
postOrder(T->left);
postOrder(T->right);
visit(T);
}
}
//叶子节点数
intleafnode(BiTreeT)
{
if(T){
if(!T->left&&!T->right)
return1;
else
leafnode(T->left)+leafnode(T->right);
}else{
return0;
}
}
intheight(BiTreeT)
{
if(T){
intlh=height(T->left);
intrh=height(T->right);
return(lh>rh?lh:rh)+1;
}else{
return0;
}
}
intmain()
{
return0;
}
⑵ 按照二叉树的递归定义,对二叉树遍历的常用算法有哪三种
前序遍历,中序遍历,后序遍历。
⑶ 关于递归算法求二叉树深度算法
u,v 分别求出当前节点左子树和右子树的深度(高度),
然后当前节点的 深度就等于左右子树里面较大的那个+1.
if (u>n) return (u+1)
return (v+1)
这句就是返回较深的+1.
u=height(T->lchild);
v=height(T->rchild);
这两句就是递归的调用,求深度了。
if (T==NULL) return 0;
这个就是终止条件了,如果没有子节点就返回。
⑷ 遍历二叉树递归算法
“这个函数的参数visit应该是另一个函数的地址是把,但我怎么感觉不管怎么递归它只是在访问根的时候被调用过一次”
首先,你是对的,visit确实是一个指向函数的指针;
然后,它只是在访问根的时候被调用过一次,这种说法就很片面了。
我觉得应该这么说:(*visit)()函数在BTreePreOrger()函数的一次执行过程中只被调用过一次,但是BTreePreOrger()函数执行了很多次,因此(*visit)()就被调用了n次(假设该树有n个节点)
⑸ 有关二叉树递归的算法
靠,缩进全被网络搞乱了,自己排版
#include <iostream>
using namespace std;
//二叉树节点
struct BiTreeNode{
int data;
BiTreeNode *left;
BiTreeNode *right;
};
//写一个类,方便二叉树的建立和删除
class BiTree{
private:
void deleteAllNode(BiTreeNode *root);
public:
BiTreeNode *root;
BiTree();
~BiTree();
void CreateTree();
void deleteLeaves(BiTreeNode *root);
bool DepthOfTheNode(BiTreeNode *currentNode,BiTreeNode *p, int depthOfFather);
void FindMaxValue(BiTreeNode *currentNode, int *maxValue);
void ExchangeLeftAndRight(BiTreeNode *currentNode);
void OutputValueAndDepthByQIANXU(BiTreeNode *currentNode, int depthOfFather); //不好意思,用了拼音
};
BiTree::BiTree()
{
root = NULL;
}
BiTree::~BiTree()
{
deleteAllNode(root);
}
void BiTree::deleteAllNode(BiTreeNode *root)
{
if (root == NULL) return;
deleteAllNode(root->left);
deleteAllNode(root->right);
cout << root->data << ' '; //用来查看当前节点是不是被删除。
delete root;
}
//手动建立一个二叉树用于测试
// 1
// / \
// 2 3
// \ /
// 4 5
void BiTree::CreateTree()
{
if (root) return;
root = new BiTreeNode;
root->data = 1;
root->left = new BiTreeNode;
root->left->data = 2;
root->right = new BiTreeNode;
root->right->data = 3;
BiTreeNode *p;
p = root->left;
p->left = NULL;
p->right = new BiTreeNode;
p->right->data = 4;
p->right->left = p->right->right = NULL;
p= root->right;
p->left = new BiTreeNode;
p->left->data = 5;
p->left->left = p->left->right = NULL;
p->right = NULL;
}
//用递归算法删除叶子
void BiTree::deleteLeaves(BiTreeNode *root)
{
if (root == NULL) return;
if (!root->left && !root->right) return; //表示是根节点(或者出错,跑到叶子节点了,这种情况应该不会),不删除
if (root->left) //当前节点有左子树
{
if (root->left->left || root->left->right) //左子树不是叶子
deleteLeaves(root->left);
else //当前节点的左子节点是叶子
{
delete root->left;
root->left = NULL;
}
}
if (root->right)
{
if (root->right->left || root->right->right)
deleteLeaves(root->right);
else //当前节点的右子节点是叶子
{
delete root->right;
root->right = NULL;
}
}
}
int depth = 0; //一个用来存储深度的全局变量,虽然在实际编程中这样用不好
//但一切为了方便。
//节点p的深度,递归法
bool BiTree::DepthOfTheNode(BiTreeNode *currentNode,BiTreeNode *p, int depthOfFather)
{
if (currentNode == NULL) return false;
if (currentNode == p) //当前节点为要找的节点
{
depth = depthOfFather + 1;
return true;;
}
if (DepthOfTheNode(currentNode->left, p, depthOfFather+1)) //找当前节点的左子树
return true;
else
return DepthOfTheNode(currentNode->right, p, depthOfFather+1);
}
//用递归找最大值,最大值存储在maxValue所指的内存 ,这里使用前序遍历
void BiTree::FindMaxValue(BiTreeNode *currentNode, int *maxValue)
{
if (currentNode == NULL) return;
*maxValue = *maxValue > currentNode->data ? *maxValue : currentNode->data;
FindMaxValue(currentNode->left, maxValue); //遍历左子树
FindMaxValue(currentNode->right, maxValue);
}
//交换左右,用前序遍历
void BiTree::ExchangeLeftAndRight(BiTreeNode *currentNode)
{
if (currentNode == NULL) return;
BiTreeNode *temp;
temp = currentNode->left;
currentNode->left = currentNode->right;
currentNode->right = temp;
ExchangeLeftAndRight(currentNode->left);
ExchangeLeftAndRight(currentNode->right);
}
//以前序次序输出一棵二叉树所有结点的数据值及结点所在层次
void BiTree::OutputValueAndDepthByQIANXU(BiTreeNode *currentNode, int depthOfFather)
{
if (currentNode == NULL) return;
cout << "节点:" << currentNode->data;
cout << "\t深度:" << depthOfFather+1 << endl;
OutputValueAndDepthByQIANXU(currentNode->left, depthOfFather+1);
OutputValueAndDepthByQIANXU(currentNode->right, depthOfFather+1);
}
int main()
{
BiTree bt;
bt.CreateTree();
//求p的深度
bt.DepthOfTheNode(bt.root, bt.root->left->right, 0);
cout << "深度:" << depth << endl;
//找最大值
int maxValue;
bt.FindMaxValue(bt.root, &maxValue);
cout << "最大值为:" << maxValue << endl;
//交换左右节点
bt.ExchangeLeftAndRight(bt.root);
//以前序次序输出一棵二叉树所有结点的数据值及结点所在层次
bt.OutputValueAndDepthByQIANXU(bt.root, 0);
//删除叶子节点
bt.deleteLeaves(bt.root);
return 0;
}
⑹ 树的递归算法
答案是正确的啊。
if(root)就是如果root!=0,这里root是一个指针,指向结构体struct node的指针,第一次进入函数它就是指向根节点A的指针
运行步骤:
如果指向A的指针不为空(不为0),打印'A',
递归调用函数指向A的左孩子节点
如果指向B的指针不为空(不为0),打印'B',
递归调用函数指向B的左孩子节点
如果指向C的指针不为空(不为0),打印'C',
递归调用函数指向C的左孩子节点
由于C的左孩子节点为空,所以本次递归traversal(root->lchild)结束,回到上一层递归中即从C的左孩子节点回到C中,然后执行traversal(root->lchild)这一句下面一句,打印出'C'
然后递归调用traversal(root->rchild);指向C的右孩子节点
如果指向E的指针不为空(不为0),打印'E',
然后再递归指向E的左孩子节点,为空再返回到E中,再次打印出'E',然后再指向E的右孩子节点,为空,E的递归结束返回上一层递归即C中,然后C也到达末尾结束返回上一层递归B中,然后执行traversal(root->lchild)这一句下面一句,打印出'B'
然后递归调用traversal(root->rchild);指向B的右孩子节点
......
如此不断进入某个节点的子节点操作后再从子节点返回父节点,层层进入再层层向上返回,从而遍历树中各个节点,最终得出结果:
A B C C E E B A D F F D G G
⑺ 先序遍历二叉树的递归算法怎样理解
二叉树的结点结构是:
1、根结点(存放结点数据)
2、左子树指针
3、右子树指计
对二叉树的遍历就是访问各个结点中根结点里存放的数据。例如:
如果结点A有左结点B,右结点C,记作A(B,C),不同结点我用"\"隔开。那么有这样一个(BitTree)二叉树表A(B,C) \B(D,E)\E(F.G)\C(空,H)\H(I.空), 自己画出来,不然我后面白讲了。
要想把所有的数据都访问到则必需按照一定的原则,即当前结点的下一个结点是哪个结点。
无论是先、中还是后序算法都是先将左结点视为下一个结点,当左结点不存在(即为空时)才将右结点视作下一个结点,如果右结点也不存在就返回当前结点的上层结点再向右访问,如此类推。
于是对二叉树的遍历问题就被抽象成三个基本步骤:
1、访问根结点。
2、访问该点的所有左子树。
3、访问该点的所有右子树。
先序遍历的策略是按123的步骤执行,中序是按213来,后序则是231,它们之间的不同只是“访问根结点”在这三个步骤中的位置。
看着你刚画好的那个BitTree跟着我的思路走。在先序遍历算法PriorOrder中,先将BitTree的头结点A传进来,按步骤123的处理。123是抽象实现,记住所表达的思想,下面是具体实现。为了避免混乱用中文数字记录步骤。
一、即是读取结点A的数据内容A(此时A为当前函数处理结点),将A的右结点C放入栈S中,S中的内容为S(C)[注意这一步是算法的一个辅助,并不是先向右访问,下同],将左结点B传给PriorOrder处理。此时读取了A
二、读取B的内容B(此时B为当前结点),将B的右结点E放入S中,S中的内容为S(C,E),将B的左结点D传给PriorOrder处理。此时读取了AB
三、D为当前结点,D的右为空没有东西放入S,S中的内容仍为S(C,E),D的左也为空,没有访问可访问的。此时就从S中取出E(因为栈是先进后出的所以取的就是E,此时S中的内容为S(C),正好是上一层没访问过的右子树),将E传给PriorOrder处理。此时读取了AB D
四、E为当前结点,对于结点E类似的有S(C,G),读取了ABDE,将F传入PriorOrder
五、F为当前结点,右为空,左也为空,读取了ABDEF,从栈中取出G传给PriorOrder处理,S的内容为S(C);
六、类似的读取了ABDEFG,从S中取出了C,传给PriorOrder处理。此时S()。
七、当前结点为C,从将C的右结点放入S,S中内容为S(H),C的左为空,从S取出H,将H传给PriorOrder处理。此时S为S().于是就读取了ABDEFGC
八,类似的读取了ABDEFGCH
九,最后ABDEFGCHF
你再对照的书上的算法想想,画画就应该能明白点。特别要理角的一点是为什么用递归算法时计算机能按这样的方式是因为函数调用是“先调用,后执行完”,或者说“后调用,先执行完”。注意我加一个“完”字