查找二叉树的从根节点到叶子节点的所有路径,递归,c/c++描述

  前面我们写过一篇,讨论如何用栈的方法找到从根节点到叶子节点的路径。其实用递归的方法也可以。但递归也要用到数组来保存已经访问过的路径节点。当根节点等于叶子节点时,表示已经找到了一条从根节点到叶子节点的完整路径。
  查找函数findAllPathAndLongest,从根节点开始,查找其左右子节点,若其有左右子节点,则说明根节点是分支节点,把根节点存入路径数组,并先后以其左右子节点为新的根节点,递归调用函数本身。如此循环地递归调用,当新的根节点等于叶子节点时,表示已经找到了一条从二叉树根节点到叶子节点的完整路径,并且已经保存在了节点数组里,数组保存路径中的每一个节点,根据此数组,我们可以输出路径,还可以找出最长路径。
  我们定义了一个变量 int stepNumber 来表示固定长度的路径数组steps[]里存入的已经走过的路径节点的最后一个节点的数组下标,数组里存入的已经走过的路径节点信息,存储在数组下标从0到下标stepNumber,此变量以值传递的形式,在调用函数与被调用子函数间传递。所以在调用函数里,可以两次调用函数本身,递归嘛,分别传入左子节点和右子节点为新的根结点,但stepNumber可以给两个被调函数传入相同的值。因为它们对应一模一样的已走过的路径。这里是巧妙的运用了函数的值传递。我们不能任何地方都使用地址传递或者引用传递(c++),如果调用函数并不想使用被改变的实参值的话。
  这刚好解决了递归调用结束时伴随的数组存储路径回溯的问题,因为查找到一条路径后,我们还要接着找到剩余的所有路径,数组数据要回溯,查看路径中的分支节点是否还有新的我们没有访问过的子节点,以此为新的根节点,继续查找。层层递归,直到二叉树的根节点的俩子节点都访问完,说明递归已彻底完成,对路径的查找也做到了不重不漏。
  在昨天还有一篇文章,讨论了迷宫问题的递归解法,两者非常的相似。读者可以参考迷宫问题那篇文章。所以知识真的可以在原有基础上再生根发芽长叶子,举一反三,融会贯通。


  完整代码如下(包含建立二叉树createBTree,输出二叉树displayBTree的逗号表达式形式,查找所有路径并顺带找出最长路径的函数findAllPathAndLongest,再就是main主函数):

#include
#include
using namespace std;
#define STACKDEPTH 15
struct BiTreeNode {
	char value;
	BiTreeNode* leftChild;
	BiTreeNode* rightChild;
};
void createBTree(BiTreeNode *&biTreeRoot,char *&ptChar) {
	struct {
		BiTreeNode* ptsBiTree[STACKDEPTH];
		int indexTop = -1;
	}sequStack;

	BiTreeNode* ptNew = NULL;
	char s ;
	int leftRight;//1 is left   2 is right
	while (*ptChar != '\0') {
		s = *ptChar;
		if ('A' <= s && s <= 'Z') {
			ptNew = new BiTreeNode;
			ptNew->value = s;
			ptNew->leftChild = ptNew->rightChild = NULL;

			if (biTreeRoot == NULL)
				biTreeRoot = ptNew;
			else if (leftRight == 1)
				sequStack.ptsBiTree[sequStack.indexTop]->leftChild = ptNew;
			else if (leftRight == 2)
				sequStack.ptsBiTree[sequStack.indexTop]->rightChild = ptNew;
		}
		else if (s == '(') {
			sequStack.indexTop++;
			sequStack.ptsBiTree[sequStack.indexTop] = ptNew;
			leftRight = 1;
		}
		else if (s == ',')
			leftRight = 2;
		else if (s == ')')
			sequStack.indexTop--;
	
		ptChar++;
	}
}
void displayBTree(BiTreeNode *&biTreeRoot) {   // 本查找方法是先序遍历
	if (biTreeRoot == NULL)
		return;//if binary tree does not exsit,return
	cout << biTreeRoot->value;
	if (biTreeRoot->leftChild != NULL || biTreeRoot->rightChild != NULL) {
		cout << '(';
		displayBTree(biTreeRoot->leftChild);
		if (biTreeRoot->rightChild != NULL) {
			cout << ',';
			displayBTree(biTreeRoot->rightChild);
		}
		cout << ')';
	}
}
void findAllPathAndLongest(BiTreeNode* steps[STACKDEPTH],int stepNumber,
	BiTreeNode *& biTreeRoot,BiTreeNode* stepLongest[STACKDEPTH],
	int &stepNumMax,int &pathNumber) {
	if (biTreeRoot == NULL)
		return;
	else {
		stepNumber++;
		steps[stepNumber] = biTreeRoot;
	}

	if (biTreeRoot->leftChild == NULL && biTreeRoot->rightChild == NULL) {
		pathNumber++;
		cout << "the " << pathNumber<<"th path : ";
		for (int i = 0; i <= stepNumber; i++)
			cout << steps[i]->value << ' ';
		cout << endl;
		if (stepNumMax < stepNumber) {
			stepNumMax = stepNumber;
			for (int i = 0; i <= stepNumMax; i++)
				stepLongest[i] = steps[i];
		}
	}
	else {
		findAllPathAndLongest(steps,stepNumber,biTreeRoot->leftChild,
			stepLongest,stepNumMax,pathNumber);
		findAllPathAndLongest(steps,stepNumber,biTreeRoot->rightChild,
			stepLongest,stepNumMax,pathNumber);
	}
}

int main() {
	char array[] = "A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))";
	char* ptChar = array;  //c++里只能这样分开定义,要不会出错。
	BiTreeNode* biTreeRoot = NULL;

	createBTree(biTreeRoot,ptChar);
	cout << "the char array is :";
	for (int i = 0; array[i] != '\0'; i++)
		cout << array[i];
	cout<< endl<< "binary tree is    :";
	displayBTree(biTreeRoot);
	cout << endl;

	BiTreeNode *steps[STACKDEPTH],*stepsLongest[STACKDEPTH];
	int stepNumMax = 0;
	int pathNumber = 0;
	findAllPathAndLongest(steps,-1,biTreeRoot,stepsLongest,stepNumMax,pathNumber);
	if (stepNumMax != -1) {
		cout << "the longest path has " << stepNumMax+ 1 << " steps : ";
		for (int i = 0; i <= stepNumMax; i++)
			cout << stepsLongest[i]->value << ' ';
	}
	return 0;
}

测试的二叉树和对应结果如下:
查找二叉树的从根节点到叶子节点的所有路径,递归,c/c++描述_第1张图片
查找二叉树的从根节点到叶子节点的所有路径,递归,c/c++描述_第2张图片






查找二叉树的从根节点到叶子节点的所有路径,递归,c/c++描述_第3张图片
查找二叉树的从根节点到叶子节点的所有路径,递归,c/c++描述_第4张图片
可见测试结果是对的。谢谢阅读

你可能感兴趣的:(数据结构c/c++描述,二叉树,c++,数据结构,算法,c语言)