由先序中序,或后序中序,可以唯一确定二叉树;完全二叉树的顺序存储,c/c++描述

2023-11-18

  这是课本里的,两个定理。由先序(根左右)、后序(左右根)可以确定根节点是哪个。由中序(左根右)可以确定左子树和右子树的范围。所以我们也找到了二叉树的左子树和右子树的先序(或后序)和中序排列。由归纳法,可得出这个构造二叉树链表的方法。
  对于完全二叉树,相对于满二叉树,只有最后两行可以不排满,是非常接近于满二叉树的,其跟满二叉树一样,父母节点与子节点的层序排列序号有2倍的规律可循。所以可以由完全二叉树的顺序排列构造其链表排列,非完全二叉树,比较稀疏的二叉树要补充至完全二叉树形式,才可以使用顺序存储,比如后两行以上的行中的空节点,以存储字符‘#’代替表示。
  本程序包含以下几个函数,程序执行思路是:由函数createBiTreeCommaExpre完成从逗号表达式建立二叉树;由函数displayBiTree输出二叉树的逗号表达式形式到屏幕,以检测建立二叉树的createBiTreeCommaExpre是否正确;由函数totalNumberOfNodes统计二叉树的总节点数。
  由函数preOrderRecursion输出二叉树的先序遍历结果至数组,(这里以节点为字符为例,所以遍历结果存储到字符数组里);由函数inOrderRecursion输出二叉树的中序排列结果至数组;由函数postOrderRecursion输出二叉树的后序遍历结果至数组。由函数dispalyArray输出字符数组至屏幕,以检验各种遍历结果是否正确。
  由函数buildBiTreePreIn根据二叉树的先序中序遍历结果重新构造新的另一个二叉树;由函数buildBiTreePostIn根据二叉树的后序中序遍历结果重新构造另一个新的二叉树;由函数buildBiTreeSequen根据二叉树的顺序存储结果构造其对应的二叉树;由函数compareBiTree比较这四个二叉树是否完全相等,以确认我们这三个构造函数是否写的正确。由主函数main调用以上所有函数。
  完整代码如下,这是主函数main所在的源文件:

#include<iostream>
#include<stdio.h>
using namespace std;
#define MAXARRAY 20
#define STACKDEPTH 15
struct BiTreeNode {
	char value;
	BiTreeNode* leftChild;
	BiTreeNode* rightChild;
};

extern void createBiTreeCommaExpre(BiTreeNode*& biTreeRoot, char* ptChar);
extern void displayBiTree(BiTreeNode*& biTreeRoot);
extern int totalNumberOfNodes(BiTreeNode*& biTreeRoot);
extern void dispalyArray(char array[]);
extern void preOrderRecursion(BiTreeNode*& biTreeRoot, char* &ptArrayPreExp);
extern void inOrderRecursion(BiTreeNode*& biTreeRoot, char* &ptArrayInExp);
extern void postOrderRecursion(BiTreeNode*& biTreeRoot, char* &ptArrayPostExp);
extern BiTreeNode * buildBiTreePreIn(char * ptPreExpre,char* ptInexpre,int length);
extern BiTreeNode * buildBiTreePostIn(char* ptPostExpre, char* ptInexpre, int length);
extern BiTreeNode * buildBiTreeSequen(char* ptSequenExpre,int location);
extern bool compareBiTree(BiTreeNode * &biTreeA, BiTreeNode* &biTreeB);

int main() {
	char arrayCommaExpress[MAXARRAY] = "A(B(D(,G)),C(E,F))";
	char* ptArrayComma = arrayCommaExpress;  //c++里只能这样分开定义,要不会出错。
	BiTreeNode* biTreeRoot = NULL;

	createBiTreeCommaExpre(biTreeRoot,arrayCommaExpress);
	cout << "the char array is :"; 
	dispalyArray(arrayCommaExpress);

	cout<< endl<< "binary tree is    :";
	displayBiTree(biTreeRoot);

	int lengthBiTree = totalNumberOfNodes(biTreeRoot);
	cout<<endl << "binary tree total nodes : " << lengthBiTree << endl;

	char arrayPreExpre[MAXARRAY] = "";
	char* ptArrayPreExp = arrayPreExpre;
	preOrderRecursion(biTreeRoot,ptArrayPreExp);
	cout <<endl<< "pre order expression  : ";
	dispalyArray(arrayPreExpre);

	char arrayInExpre[MAXARRAY] = "";
	char* ptArrayInExpre = arrayInExpre;
	inOrderRecursion(biTreeRoot,ptArrayInExpre);
	cout << endl << "in order expression   : ";
	dispalyArray(arrayInExpre);

	char arrayPostExpre[MAXARRAY] = "";
	char* ptArrayPostExpre = arrayPostExpre;
	postOrderRecursion(biTreeRoot,ptArrayPostExpre);
	cout << endl << "post order expression : ";
	dispalyArray(arrayPostExpre);

	char arraySequenExpre[MAXARRAY] = "9ABCD#EF#G";
	char* ptArraySequenExpre = arraySequenExpre;
	cout << endl << "sequential order expression(手工计算的) : ";
	dispalyArray(arraySequenExpre);
	cout << endl;

	BiTreeNode* biTreePreIn = buildBiTreePreIn(arrayPreExpre,
		arrayInExpre,lengthBiTree);
	BiTreeNode* biTreePostIn = buildBiTreePostIn(arrayPostExpre,
		arrayInExpre,lengthBiTree);
	BiTreeNode* biTreeSequen = buildBiTreeSequen(arraySequenExpre,1);

	cout << endl;
	cout << "Succeed in building BiTree according to pre and in expression ? ";
	cout << (compareBiTree(biTreeRoot, biTreePreIn) ? "yes" : "no" )<< endl;
	displayBiTree(biTreePreIn);
	cout << endl;

	cout << endl;
	cout << "Succeed in building BiTree according to post and in expression ? ";
	cout << (compareBiTree(biTreeRoot, biTreePostIn) ? "yes" : "no") << endl;
	displayBiTree(biTreePostIn);
	cout << endl;

	cout << endl;
	cout << "Succeed in building BiTree according to sequential expression ? ";
	cout << (compareBiTree(biTreeRoot, biTreeSequen) ? "yes" : "no") << endl;
	displayBiTree(biTreeSequen);
	cout << endl;

	cout << endl <<"thank you for your practices ." << endl;

	return 0;
}

  这是各个函数所在的源文件(大量应用了递归,所以不算太长):

#include<iostream>
#include<stdio.h>
using namespace std;
#define STACKDEPTH 15
#define MAXARRAY 20
struct BiTreeNode {
	char value;
	BiTreeNode* leftChild;
	BiTreeNode* rightChild;
};
void createBiTreeCommaExpre(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 displayBiTree(BiTreeNode*& biTreeRoot) {   // 本查找方法是先序遍历
	if (biTreeRoot == NULL)
		return;//if binary tree does not exsit,return
	cout << biTreeRoot->value;
	if (biTreeRoot->leftChild != NULL || biTreeRoot->rightChild != NULL) {
		cout << '(';
		displayBiTree(biTreeRoot->leftChild);
		if (biTreeRoot->rightChild != NULL) {
			cout << ',';
			displayBiTree(biTreeRoot->rightChild);
		}
		cout << ')';
	}
}

int totalNumberOfNodes(BiTreeNode*& biTreeRoot) {
	if (biTreeRoot == NULL)
		return 0;
	return totalNumberOfNodes(biTreeRoot->leftChild) +
		totalNumberOfNodes(biTreeRoot->rightChild) + 1;
}

void dispalyArray(char array[]) {
	char* pt = array;
	while (*pt != '\0') {
		cout << *pt;
		pt++;
	}
}

void preOrderRecursion(BiTreeNode*& biTreeRoot, char* &ptArrayPreExp) {
	if (biTreeRoot == NULL)
		return;
	*ptArrayPreExp = biTreeRoot->value;
	ptArrayPreExp++;

	preOrderRecursion(biTreeRoot->leftChild,ptArrayPreExp);
	preOrderRecursion(biTreeRoot->rightChild,ptArrayPreExp);
}

void inOrderRecursion(BiTreeNode*& biTreeRoot, char* &ptArrayInExp) {
	if (biTreeRoot == NULL)
		return;
	
	inOrderRecursion(biTreeRoot->leftChild,ptArrayInExp);
	
	*ptArrayInExp = biTreeRoot->value;
	ptArrayInExp++;

	inOrderRecursion(biTreeRoot->rightChild,ptArrayInExp);

}
void postOrderRecursion(BiTreeNode*& biTreeRoot, char* &ptArrayPostExp) {
	if (biTreeRoot == NULL)
		return;

	postOrderRecursion(biTreeRoot->leftChild,ptArrayPostExp);
	postOrderRecursion(biTreeRoot->rightChild,ptArrayPostExp);

	*ptArrayPostExp = biTreeRoot->value;
	ptArrayPostExp++;

}

BiTreeNode* buildBiTreePreIn(char* ptPreExpre, char* ptInexpre, int length) {
	if (length <= 0)
		return NULL;
	 
	char root = *ptPreExpre;
	
	BiTreeNode* biTreeRoot = new BiTreeNode;
	biTreeRoot->value = root;

	char* ptRoot = ptInexpre;
	while (*ptRoot != root)
		ptRoot++;
	int lengthLeftChilds = ptRoot - ptInexpre;
	int lengthRightChilds = length - 1 - lengthLeftChilds;

	biTreeRoot->leftChild = 
		buildBiTreePreIn(ptPreExpre + 1,ptInexpre,lengthLeftChilds);
	biTreeRoot->rightChild = buildBiTreePreIn(ptPreExpre + lengthLeftChilds + 1,
		ptRoot + 1,lengthRightChilds);

	return biTreeRoot;
}
BiTreeNode* buildBiTreePostIn(char* ptPostExpre, char* ptInexpre, int length) {
	if (length <= 0)
		return 0;

	char root = *(ptPostExpre + length - 1);
	BiTreeNode* biTreeRoot = new BiTreeNode;
	biTreeRoot->value = root;

	char* ptRoot = ptInexpre;
	while (*ptRoot != root)
		ptRoot++;

	int lengthLeftChilds = ptRoot - ptInexpre;
	int lengthRightChilds = length - 1 - lengthLeftChilds;

	biTreeRoot->leftChild = 
		buildBiTreePostIn(ptPostExpre,ptInexpre,lengthLeftChilds);
	biTreeRoot->rightChild = buildBiTreePostIn(
		ptPostExpre + lengthLeftChilds,ptRoot + 1,lengthRightChilds);

	return biTreeRoot;
}
BiTreeNode* buildBiTreeSequen(char* ptSequenExpre,int location) {
	if (*(ptSequenExpre + location) == '\0' || 
		*(ptSequenExpre + location) == '#')
		return NULL;
	
	BiTreeNode* biTreeRoot = new BiTreeNode;
	biTreeRoot->value = *(ptSequenExpre + location);

	biTreeRoot->leftChild = buildBiTreeSequen(ptSequenExpre,location * 2);
	biTreeRoot->rightChild = buildBiTreeSequen(ptSequenExpre,location * 2 + 1);

	return biTreeRoot;
}
bool compareBiTree(BiTreeNode* &biTreeA, BiTreeNode* &biTreeB) {
	if (biTreeA == NULL && biTreeB == NULL)
		return true;

	if (biTreeA == NULL && biTreeB != NULL || biTreeA != NULL && biTreeB == NULL)
		return false;

	if (biTreeA->value != biTreeB->value)
		return false;

	return compareBiTree(biTreeA->leftChild, biTreeB->leftChild) &&
		compareBiTree(biTreeA->rightChild,biTreeB->rightChild);
}

  测试结果及对应的二叉树如下:
在这里插入图片描述

在这里插入图片描述

  谢谢阅读

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

由先序中序,或后序中序,可以唯一确定二叉树;完全二叉树的顺序存储,c/c++描述 的相关文章

随机推荐

  • LeetCode-283. 移动零【数组,双指针】

    LeetCode 283 移动零 数组 双指针 题目描述 解题思路一 首先想到的是双指针 但是不行 非零元素的位置会改变 解题思路二 改进的是每次从当前0元素的位置取后面第一个非0元素替换过来 替换之和那个break非常重要 解题思路三 优
  • Future 和 Callable

    一 Runnable 缺陷 不能返回一个返回值 不能抛出 checked Execption 二 Callable接口 类似于Runnable 被其他线程执行的任务 实现call方法 有返回值 三 Future的作用 Callable和Fu
  • 【infiniband】 MAD、 uMAD、Verbs、RDMACM

    1 MAD Management Datagram MAD是InfiniBand网络中用于管理和配置的数据报文 它包含了各种类型的管理操作 如查询端口状态 配置端口参数等 MAD通常用于执行网络管理任务 2 uMAD User MAD uM
  • 模板类 通用数组的实现

    实现自定义数组 重载 lt lt 运算符 并且数组可以使用自定义类 头文件 ifndef MYARRAY H define MYARRAY H include
  • pandas datetime与时间戳互相转换,字符串转换datetime

    参考pandas to datetime的api 字符串转换为pandas datetime 通过to datetime函数可以把字符串转换为pandas datetime df pd DataFrame date 2011 04 24 0
  • python的xlrd、xlwt模块/pymsql使用

    xlrd模块 https www cnblogs com machangwei 8 p 10736528 html label0 xlwt模块https www cnblogs com machangwei 8 p 10738244 htm
  • Filter过滤器实现权限拦截

    一 要求 用户登陆之后才能进入主页 用户注销之后不能进入首页 二 思路 用户登陆之后 向session中放入用户的数据 进入主页的时候要判断用户是否已经登陆 在过滤器中实现 public void doFilter ServletReque
  • 电脑怎样连接打印机?分享4个简单操作!

    为了更方便学习 我买了一个打印机来打印需要用的资料 但是操作了半天还是没连接上 想请问一下有经验的朋友是怎么将打印机与电脑进行连接的呢 在现代人的工作和生活中 打印机是一个重要的设备 我们可以利用打印机进行资料 文件等的打印 但是也会有很多
  • SpringBoot调用PageHelper.startPage(Object params)报错:分页查询缺少必要的参数:XXX

    问题描述 项目中使用了MyBatis分页插件 调用以下方法实现分页 无论传入JavaBean还是Map都报错 分页查询缺少必要的参数 XXX Map
  • 【Docker】云原生利用Docker确保环境安全、部署的安全性、安全问题的主要表现和新兴技术产生

    前言 Docker 是一个开源的应用容器引擎 让开发者可以打包他们的应用以及依赖包到一个可移植的容器中 然后发布到任何流行的Linux或Windows操作系统的机器上 也可以实现虚拟化 容器是完全使用沙箱机制 相互之间不会有任何接口 云原生
  • Python学习 第二章 数据类型

    Python学习 第二章 数据类型上 1 数字 1 1 整型 int 1 2 浮点型 float 1 3 布尔类型 bool 1 4 代码实现 1 5 复数 2 字符串 string 2 1 如果字符串内容中出现了引号 2 2 代码实现 2
  • pandas生成excel文件

    可以使用pandas中的to excel 函数将DataFrame数据写入Excel文件 例如 import pandas as pd 创建测试数据 data name Mike John Bob age 25 32 45 city New
  • STM-32:SPI通信协议/W25Q64简介—软件SPI读写W25Q64

    目录 一 SPI简介 1 1电路模式 1 2通信原理 1 3SPI时序基本单元 1 3 1起始和终止 1 3 2交换字节 二 W25Q64 2 1W25Q64简介 2 2W25Q64硬件电路 2 3W25Q64框图 2 4Flash操作注意
  • double类型精度丢失问题以及解决方法

    double类型精度丢失问题 1 加法运算 public static void main String args double number1 1 double number2 20 2 double number3 300 03 dou
  • arcgis for android 学习 - (5) 在地图指定位置添加“标记“,并尝试选中它

    我做一个例子 1 首先显示一个地图 2 点击 添加要素 按钮后再次点击地图 将会在地图上添加 红色的位置标记 3 再次点击按钮后 这时 就可以点击刚刚添加的 红色的位置标记 就可以查看到 该标记关联到得属性值 布局
  • NO.17 浅谈共识机制(POW、POS、DPOS、PBFT、POP)

    区块链是一种去中心化的分布式账本 可以简单理解为分布在全球各个节点的分布式数据库 数据库由区块按时间顺序相连而成 区块中记录的是数笔交易 为了能支持这一套系统的运行 需要各节点矿工的参与 他们参与的主要原因是因为有奖励 奖励可以去交易所换成
  • kafka消费者客户端线程安全以及多线程实现并发读取消息

    kafka的生产者客户端Producer是线程安全的 但是消费者客户端是非线程安全的 每次操作时都会调用accqure方法用来确定当前只有一个线程操作 如果有多个线程在操作 会抛出CME异常 针对这种情况 为了能够多线程更快速的读取消息 可
  • 【Python 1-17】Python手把手教程之——文件的读写以及I/O操作

    作者 弗拉德 来源 弗拉德 公众号 fulade me 从文件中读取数据 文本文件可存储的数据量很多 每当需要分析或修改存储在文件中的信息时 读取文件都很有用 对数据分析应用程序来说尤其 如此 例如 你可以编写一个这样的程序 读取一个文本文
  • 研发人员欠缺的“不要脸”文化

    一直感觉研发人员相对市场人员确实缺少点什么 今天听到一个原华为的人说华为的文化中有一个 不要脸 文化 讲的就是研发人员要特别注意的事项 特别说明 不要脸 三个字 据说是任正非认为这样好记 才取得名字 这三点是 抬头看路 找人问路 请人带路
  • 由先序中序,或后序中序,可以唯一确定二叉树;完全二叉树的顺序存储,c/c++描述

    这是课本里的 两个定理 由先序 根左右 后序 左右根 可以确定根节点是哪个 由中序 左根右 可以确定左子树和右子树的范围 所以我们也找到了二叉树的左子树和右子树的先序 或后序 和中序排列 由归纳法 可得出这个构造二叉树链表的方法 对于完全二