C++数据结构二叉树的相关操作,完整版本
Posted Roam-G
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++数据结构二叉树的相关操作,完整版本相关的知识,希望对你有一定的参考价值。
//程序5.3 --194-利用二叉链表的二叉树类定义
#include <iostream>
#include "Queue.h"
#include <stdlib.h>
#include "Stack.h"
template <class T>
struct BinTreeNode {
T data;
BinTreeNode<T>* leftChild, * rightChild;
BinTreeNode() : leftChild(NULL), rightChild(NULL) {}
BinTreeNode(T x, BinTreeNode<T>* l = NULL, BinTreeNode<T>* r = NULL)
: data(x), leftChild(l), rightChild(r) {}
};
template <class T>
class BinaryTree
{
public:
BinaryTree() : root(NULL) {}
BinaryTree(T value) : RefValue(value), root(null) {}
BinaryTree(BinaryTree<T>& s);
~BinaryTree() { destroy(root); }
//判断是否为空
bool IsEmpty() {
return (root == NULL) ? true : false;
}
//返回父节点
BinTreeNode<T>* Parent(BinTreeNode<T>* current) {
return (root == NULL || root == current) ? NULL : Parent(root, current);
}
//返回左子女
BinTreeNode<T>* LeftChild(BinTreeNode<T>* current) {
return (current != NULL) ? current->leftChild : NULL;
}
//返回右子女
BinTreeNode<T>* RightChild(BinTreeNode<T>* current) {
return (current != NULL) ? current->rightChild : NULL;
}
int Height() {//返回树高度
return Height(root);
}
int Size() {
return Size(root);//返回结点数
}
BinTreeNode<T>* getRoot() const {//取根
return root;
}
void preOrder(void (*visit)(BinTreeNode<T>* p)) {//前序遍历
preOrder(root, visit);
}
void inOrder(void (*visit)(BinTreeNode<T>* p)) {//中序遍历
inOrder(root, visit);
}
void postOrder(void (*visit)(BinTreeNode<T>* p)) {//后序遍历
postOrder(root, visit);
}
void levelOrder(void (*visit)(BinTreeNode<T>* p));//层次遍历
int Insert(const T item);
//搜索
BinTreeNode<T>* Find(T item) const;
protected:
BinTreeNode<T>* root;
T RefValue;
void CreateBinTree(istream& in, BinTreeNode<T>*& subTree);
bool Insert(BinTreeNode<T>*& subTree, const T& x);
void destroy(BinTreeNode<T>*& subTree);
bool Find(BinTreeNode<T>* subTree, const T& x) const;
//复制
BinTreeNode<T>* Copy(BinTreeNode<T>* orignode);
//返回树高度
int Height(BinTreeNode<T>* subTree);
//返回结点数
int Size(BinTreeNode<T>* subTree);
//返回父节点
BinTreeNode<T>* Parent(BinTreeNode<T>* subTree, BinTreeNode<T>* current);
//搜寻X
BinTreeNode<T>* Find(BinTreeNode<T>* subTree, const T& x) const;
//前序遍历输出
void Traverse(BinTreeNode<T>* subTree, ostream& out);
//前序遍历
void preOrder(BinTreeNode<T>* subTree, void (*visit)(BinTreeNode<T>* p));
//中序遍历
void inOrder(BinTreeNode<T>* subTree, void (*visit)(BinTreeNode<T>* p));
//后序遍历
void postOrder(BinTreeNode<T>* subTree, void (*visit)(BinTreeNode<T>* p));
//重载操作,输入
friend istream& operator>>(istream& in, BinaryTree<T>& Tree);
//重载操作,输出
friend ostream& operator<<(ostream& out, BinTreeNode<T>& Tree);
};
//程序5.4 --196--二叉树 部分成员函数的实现
template<class T>
void BinaryTree<T>::destroy(BinTreeNode<T>*& subTree) {
//私有函数,若 subTree 不为空,删除 subtree 的子树
if (subTree != NULL) {
destroy(subTree->leftChild);
destroy(subTree->rightChild);
delete subTree;
}
};
template<class T>
BinTreeNode<T>* BinaryTree<T>::Parent(BinTreeNode<T>* subTree, BinTreeNode<T>* current) {
//私有函数,从subtree 开始,搜索结点current的父节点,找到返回地址,否则返回null
if (subTree == NULL) {
return NULL;
}
if (subTree->leftChild == current || subTree->rightChild == current) {
return subTree;//找到 ,返回父节点的subtree
}
BinTreeNode<T>* p;
//递归在左子树中搜索
if ((p = Parent(subTree->leftChild, current)) != NULL) {
return p;
}
else {
//递归在右子树中搜索
return Parent(subTree->rightChild, current);
}
};
//私有函数,搜索并输出,根为subTree的二叉树
template<class T>
void BinaryTree<T>::Traverse(BinTreeNode<T>* subTree, ostream& out) {
if (subTree != NULL) {
//输出subtree的数据值
out << subTree->data << " ";
//递归搜索并输出 subtree 的左子树
Traverse(subTree->leftChild, out);
//递归搜索并输出 subtree 的右子树
Traverse(subTree->rightChild, out);
}
};
//重载操作,输入并建立一颗二叉树,in 是输入流对象
template<class T>
istream& operator>>(istream& in, BinaryTree<T>& Tree) {
CreateBinTree(in, Tree.root);
return in;
};
//重载 操作 ,输出一颗二叉树,OUT是输出流对象
template<class T>
ostream& operator<<(ostream& out, BinaryTree<T>& Tree) {
out << "二叉树的前序遍历:\\n";
Tree.Traverse(Tree.root, out);
out << endl;
return out;
}
//程序5.5--197-输入广义表 建立二叉树
void CreateBinTree(istream& in, BinTreeNode<char>*& BT) {
//从输入流in输入二叉树的广义表表示建立对应 的二叉树
Stack<BinTreeNode<char>* > stack;
BT = NULL;
BinTreeNode<char>* p, * t;
int k;//k用作处理左右子树标记。
char ch;
in >> ch;
while (ch != RefValue) {//逐个字符处理# = RefValue
switch (ch) {
case '(':
stack.Push(p);
k = 1;
break;
case ')':
stack.Pop(t);
break;
case ',':
k = 2;
break;
default:
p = new BinTreeNode<ch>;
if (BT == NULL) {
BT = p;
}
else if (k == 1) {
stack.getTop(t);
t->LeftChild = p;
}
else {
stack.getTop(t);
t->RightChild = p;
}
}
in >> ch;
}
};
//程序5.6 7 8二叉树的三种遍历--199
//1.前序遍历
template<class T>
void BinaryTree<T>::preOrder(BinTreeNode<T>* subTree, void (*visit)(BinTreeNode<T>* p)) {
if (subTree != NULL) {
visit(subTree);
preOrder(subTree->leftChild, visit);
preOrder(subTree->rightChild, visit);
}
}
//2,中序遍历
template<class T>
void BinaryTree<T>::inOrder(BinTreeNode<T>* subTree, void (*visit)(BinTreeNode<T>* p)) {
if (subTree != NULL) {
inOrder(subTree->leftChild, visit);
visit(subTree);
inOrder(subTree->rightChild, visit);
}
}
//3.后序遍历
template<class T>
void BinaryTree<T>::postOrder(BinTreeNode<T>* subTree, void (*visit)(BinTreeNode<T>* p)) {
if (subTree != NULL) {
postOrder(subTree->leftChild, visit);
postOrder(subTree->rightChild, visit);
visit(subTree);
}
}
//应用后序遍历 ,5.9 统计结点总数
template<class T>
int BinaryTree<T>::Size(BinTreeNode<T>* subTree)const {
if (subTree == NULL) {
return 0;
}
else {
//左右子树+根结点
return 1 + Size(subTree->leftChild) + Size(subTree->rightChild);
}
};
template<class T>
int BinaryTree<T>::Height(BinTreeNode<T>* subTree) {
if (subTree == NULL) {
return 0;
}
else {
int i = Height(subTree->leftChild);
int j = Height(subTree->rightChild);
//高度 是 子树+1 (根结点的高度)
return (i < j) ? j + 1 : i + 1;
}
};
//5.10前序遍历的应用:复制二叉树
template<class T>
BinaryTree<T>::BinaryTree(const BinaryTree<T>& s) {
//公共函数, 复制构造函数
root = Copy(s.root);
};
template<class T>
BinTreeNode<T>* BinaryTree<T>::Copy(BinTreeNode<T>* orignode) {
//私有函数,该函数返回一个 指针,它给出一个以orignode为根结点的二叉树的副本
if (orignode == NULL) {
//根结点为空,返回null
return NULL;
}
BinTreeNode<T>* temp = new BinTreeNode<T>;//创建xin根结点
temp->data = orignode->data;//传送数据
//复制左右子树
temp->leftChild = Copy(orignode->leftChild);
temp->rightChild = Copy(orignode->rightChild);
//返回根指针
return temp;
};
//5.11 判断两个 二叉树是否相等【利用前序遍历 】
template<class T>
int operator==(const BinaryTree<T>& s, const BinaryTree<T>& t) {
//判断两个二叉树的等价性,假定它是 binaryTree类的友元函数
return (equal(s.root, t.root)) ? true : false;
};
template<class T>
bool equal(BinTreeNode<T>* a, BinTreeNode<T>* b) {
//若a和b子树不等同,返回false,否则 true 。假定 它是 BinTreeNode的友元函数
if (a == NULL && b == NULL) {//两个都是 null
return true;
}
//两者都不为空,根结点都相同,左右子树都相同。
if (a != NULL && b != NULL && a->data == b->data &&
equal(a->leftChild, b->leftChild) &&
equal(a->rightChild, b->rightChild)) {
//只管写思路,其他的交给夸戳!
return true;
}else{
return false;
}
};
//5.12 以前序遍历 建立二叉树
template<class T>
void BinaryTree<T>::CreateBinTree(ifstream& in, BinTreeNode<T>*& subTree) {
T item;
//未读完,读入并建立 树
if (!in.eof()) {
//读入根结点的值
in >> item;
if (item != RefValue) {
//建立根结点
subTree = new BinTreeNode<T>(item);
if (subTree == NULL) {
cerr << "存储分配错误!" << endl;
exit(1);
}
//递归建立左右子树
CreateBinTree(in, subTree->leftChild);
CreateBinTree(in, subTree->rightChild);
}else {
//封闭指向空子树
subTree = NULL;
}
}
};
//5.13 以为广义表的形式输出二叉树的算法
template<class T>
void PrintBTree(BinTreeNode<T>* BT) {
if (BT != NULL) {
cout << BT->data;//先输出根结点
if (BT->leftChild != NULL || BT->rightChild != NULL) {
cout << '(';
PrintBTree(BT->leftChild);
cout << ",";
if (BT->rightChild != NULL) {
PrintBTree(BT->rightChild);
}
cout << ')';
}
}
};
//5.14二叉树 前序遍历的 非递归 算法 该方法 只有 右子女进栈!
template<class T>
void BinaryTree<T>::preOrder(void (*visit)(BinTreeNode<T>* p)) {
Stack<BinTreeNode<T>*> S;
BinTreeNode<T>* p = root;
//先在栈中存入一个 null ,然后遇到 根结点 就访问,如果有 右子女 就压入栈。
//返回就 前进到 左子女 并访问了,如果 左子女为null,就弹出 栈顶元素 并访问了。
S.Push(NULL);
while (p != NULL) {
//首先访问根结点
visit(p);
//若 有右子女 就压入栈
if (p->rightChild != NULL) {
S.Push(p->rightChild);
}
//若 有左子女 就前进到左子女
if (p->leftChild != NULL) {
p->leftChild;
}
//否则,弹出栈顶元素
else
{
S.Pop(p);
}
}
};
//5.15 修改 5.14 ,使得 左右子女都进展。先进 右子女,后进左子女。
template<class T>
void BinaryTree<T>::preOrder(void (*visit)(BinTreeNode<T>* p)) {
Stack<BinTreeNode<T>*> S;
BinTreeNode<T>* p;
//先把根结点压入栈
S.Push(root);
while (!S.IsEmpty()) {
//只要栈 不为空,就弹出 栈顶元素,并访问
S.Pop(p);
visit(p);
//先压入右子女
if (p->rightChild != NULL) {
S.Push(p->rightChild);
}
//后 压入 做左子女 因为 栈是FILO
if (p->leftChild != NULL) {
S.Push(p->leftChild);
}
}
};
//5.16 层次遍历 需要用到 队列
template<class T>
void BinaryTree<T>::levelOrder(void (*visit)(BinTreeNode<T>* p)) {
Queue<BinTreeNode<T>* > Q;
BinTreeNode<T>* p = root;
//先 把根结点 入队
Q.EnQueue(p);
while (!Q.IsEmpty()) {
// 队首元素出队,并访问
Q.DeQueue(p);
visit(p);
//把它的左子女入队
if (p->leftChild != NULL) {
Q.EnQueue(p->leftChild);
}
//把它的右子女 入队 层次遍历,先左后右
if (p->rightChild != NULL) {
Q.EnQueue(p->rightChild);
}
}
};
//5.17 利用栈的 中序遍历 非递归算法
template<class T>
void BinaryTree<T>::inOrder(void (*visit)(BinTreeNode* p)) {
Stack<BinTreeNode<T>*> S;
//p是遍历指针,从根结点 开始
BinTreeNode<T>* p = root;
do {
//遍历指针未到 最左下 的结点,不空
while (p != NULL) {
//该子树 沿途结点 进栈
S.Push(p);
//遍历指针进入到左子女结点
p = p->leftChild;
}
if (!S.IsEmpty()) {
//栈 不空时,退出 并 访问
S.Pop(p);
visit(p);
//遍历指针进入到 右子女结点
p = p->rightChild;
}
} while (p != NULL || !S.IsEmpty());
};
//利用栈的后序遍历 非递归算法
//5.18 后序遍历 中 所用栈的结点定义
template<T>
struct stkNode
{
//指向树结点的指针
BinTreeNode<T>* ptr;
//结点 退栈标记
enum tag { L, R };
//构造函数
stkNode(BinTreeNode<T>* N = NULL) :ptr(N), tag(L) {}
};
//后序遍历的非递归算法
template<T>
void BinaryTree<T>::postOrder(void (*visit)(BinTreeNode<T>* p)) {
Stack<stkNode<T>> S;
stkNode<T> w;
//p是 遍历指针
BinTreeNode<T>* p = root;
do
{
//左子树 经过结点加L进栈
while (p != NULL) {
w.ptr = p;
w.tag = L;
S.Push(w);
//向 最左结点 走下去
p = p->leftChild;
}
//继续循环标记,用于R
int continuel = 1;
while (continuel && !S.IsEmpty()) {
//栈不空 退栈
S.Pop(w);
p = w.ptr;
//判断 栈顶的tag标记
switch (w.tag) {
case L:
//从 左子树 退回,修改栈顶tag
w.tag = R;
S.Push(w);
continuel = 0;
//向右子树 遍历下去
p = p->rightChild;
break;
case R:
//从右子树结点退回,访问根结点
visit(p);
break;
}
}
//还有未遍历结点,继续循环
} while (!S.IsEmpty());
cout << endl;
};
//5.20 利用 前序遍历和中序遍历 构造二叉树
template<T>
BinTreeNode<T>* createBinaryTree(T* VLR, T* LVR, int n) {
if (n == 0) {
return NULL;
}
int k = 0;
//在中序遍历 序列中 寻找根结点
while (VLR[0] != LVR[k])
k++;
//创建 根结点
BinTreeNode<T>* t = new BinTreeNode<T>(VLR[0]);
//从前序遍历 VLR+1开始对中序遍历的0~k-1左子序列的k个元素 递归建立 左子树
t->leftChild = createBinaryTree(VLR + 1, LVR, k);
//从前序遍历 VLR+K+1开始对中序遍历的K+1~N-1右子序列的n-k-1个元素 递归建立 右子树
t->rightChild = createBinaryTree(VLR + k + 1, LVR + k + 1, n - k - 1);
//构造出的 二叉树根指针 由函数返回。
return t;
};
以上是关于C++数据结构二叉树的相关操作,完整版本的主要内容,如果未能解决你的问题,请参考以下文章
c++二叉树按层序遍历顺序输入(由上到下),先序遍历顺序输出,求完整代码
数据结构(C语言版)严蔚敏---二叉树遍历操作二叉树的相关代码