二叉树的中序遍历 个人笔记
这颗树只是普通的二叉树,并不是二叉搜索树
二叉树的定义和实现
源代码
#include <stdio.h>
#include <stdlib.h>
#include <stack>
#define MAX_SIZE 10
enum CHILD {
LCHILD, //左孩子
RCHILD //右孩子
};
//树的结构体类型声明
typedef struct _BiTree {
int data; //数据
struct _BiTree* lchild, * rchild;
}BiTree;
//创建一个二叉树的根节点;
void initTree(BiTree*& root,int value) {
root = (BiTree*)malloc(sizeof(BiTree));
root->data = value;
root->lchild = root->rchild = NULL;
}
/******
************************
*函数参数 : parent -- 创建节点的根节点
* value - 节点中的数据
* child - 插入根节点的位置节点(左孩子节点或者有孩子节点)
*
*函数作用: 创建树的节点
*
*函数返回值: 返回创建好的节点
* 如果插入的位置有节点的话插入失败返回NULL;
*/
BiTree* CreateTree(BiTree* parent, int value, enum CHILD child) {
if (parent == NULL) return NULL;
BiTree* node = (BiTree*)malloc(sizeof(BiTree));
node->data = value;
node->lchild = NULL;
node->rchild = NULL;
switch (child) {
case LCHILD:
if (parent->lchild == NULL) {
parent->lchild = node;
break;
}
else {
printf("该节点有左子节点!创建失败");
free(node);
return NULL;
}
case RCHILD:
if (parent->rchild == NULL) {
parent->rchild = node;
break;
}
else {
printf("该节点有右子节点!创建失败");
free(node);
return NULL;
}
}
return node;
}
int main(void) {
BiTree* root = NULL;
//初始化根节点
initTree(root,1);
//创建根节点的左子节点
CreateTree(root, 2, LCHILD);
//用这个二叉树的根节点的左子节点作为作为根节点创建左子节点
CreateTree(root->lchild, 5, LCHILD);
//用这个二叉树的根节点的左子节点作为根节点创建右子节点
CreateTree(root->lchild, 6, RCHILD);
//创建根节点的右子节点
CreateTree(root, 3, RCHILD);
//用这个二叉树的根节点的右子节点子节点作为根节点创建左子节点
CreateTree(root->rchild, 7, LCHILD);
traversalTree(root);
BiTree* ret= copyTree(root);
printf("\n");
inorder(root);
return 0;
}
创建好的二叉树的模型
二叉树使用递归先序.中序.后序遍历的本质
先序遍历
先访问根节点再访问左子树最后访问右子树
遍历结果:
-1–2--5–6--3–7-
//先序遍历树(使用递归);
void traversalTree(BiTree* root) {
if (root == NULL) {
return;
}
printf("-%d-", root->data);
traversalTree(root->lchild);
traversalTree(root->rchild);
}
中序遍历
先访问左子树再访问根节点最后访问右子树
遍历结果:
-5–2--6–1--7–3-
//中序遍历树(使用递归);
void traversalTree(BiTree* root) {
if (root == NULL) {
return;
}
printf("-%d-", root->data);
traversalTree(root->lchild);
traversalTree(root->rchild);
}
后序遍历
先访问左子树再访问右子树最后访问根节点
遍历结果:
-5–6--2–7--3–1-
//后序遍历树(使用递归);
void traversalTree(BiTree* root) {
if (root == NULL) {
return;
}
traversalTree(root->lchild);
printf("-%d-", root->data);
traversalTree(root->rchild);
}
本质
如果去掉printf打印语句三种遍历代码是一致的也就是说访问路径是一样只不过打印节点的时机是不一样的且每一个节点都会经历三次;
二叉树用栈实现中序遍历
用类模板stack容器实现
原理:
一.循环判断节点是否有左子节点有则这节点入栈没有左子节点结束循环
保存没有左子节点的节点打印节点并进入二
二.节点判断是否有右子节点有则重复一,没有进入三
三.删除并保存栈顶元素打印栈顶元素,进入二
栈为空结束
/*
******************
*函数参数 : root - 根节点
* stack - 栈的类模板
*
*函数作用: 找到从根节点开始最左子节点
*
*函数返回值: 返回最左子节点的指针
***************
*/
BiTree* getMostLChild(BiTree* root, std::stack<BiTree*>* Stack) {
if (root == NULL) {
return NULL;
}
/* 如果root有左子节点就入栈*/
while (root->lchild) {
Stack->push(root);
root = root->lchild;
}
/*root就是没有左子节点这个节点没有入栈*/
return root;
}
/*
*使用stack类模板完成中序遍历
*
*
*/
void inorder2(BiTree* root) {
if (root == NULL) {
return;
}
std::stack<BiTree*> Stack;
BiTree* temp = getMostLChild(root, &Stack);
while (1) {
printf("-%d-", temp->data);
if (temp->rchild) {
temp = getMostLChild(temp->rchild, &Stack);
}
else if(!Stack.empty()) {
temp = Stack.top();
Stack.pop();
}
else {
break;
}
}
}
temp = getMostLChild(root, &Stack);
while (1) {
printf("-%d-", temp->data);
if (temp->rchild) {
temp = getMostLChild(temp->rchild, &Stack);
}
else if(!Stack.empty()) {
temp = Stack.top();
Stack.pop();
}
else {
break;
}
}
}