1
0
Fork 0
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

481 lines
14 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#ifndef BITREE_H
#define BITREE_H
#include <iostream>
#include <queue>
using namespace std;
#include "LinkedStack.h"
#include "SeqQueue.h"
#include "SeqStack.h"
#include <assert.h>
#include <stdlib.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(new BinTreeNode<T>(value)) {}
BinaryTree(BinaryTree<T> &s);
~BinaryTree()
{
destroy();
}
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;
}
void destroy()
{
destroy(root);
}
int Height() { return Height(root); }
int Size() { return Size(root); }
BinTreeNode<T> *getRoot() const { return root; }
void setRoot(BinTreeNode<T> *p) { root = p; }
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 NonR_preOrder(void (*visit)(BinTreeNode<T> *p)); //非递归前序遍历
void NonR_preOrder1(void (*visit)(BinTreeNode<T> *p)); //非递归前序遍历
void NonR_inOrder(void (*visit)(BinTreeNode<T> *p)); //非递归中序遍历
void NonR_postOrder(void (*visit)(BinTreeNode<T> *p)); //非递归后续遍历
void levelOrder(void (*visit)(BinTreeNode<T> *p));
BinTreeNode<T> *Insert(BinTreeNode<T> *curr, const T &x, int d); //作业实现在curr结点左/右插入子女结点x
BinTreeNode<T> *Find(T item) const //作业递归算法实现查找item
{
return Find(root, item);
}
int NonR_Height(); //作业:使用非递归方法求树高度
bool IsBalanced() //作业:递归算法判断二叉树是否为平衡二叉树
{
int height;
return IsBalanced(root, height);
}
protected:
BinTreeNode<T> *root;
T RefValue;
void CreateBinTree(istream &in, BinTreeNode<T> *&subTree);
void destroy(BinTreeNode<T> *&subTree);
BinTreeNode<T> *Copy(BinTreeNode<T> *orignode);
int Height(BinTreeNode<T> *subTree) const;
int Size(BinTreeNode<T> *subTree) const;
BinTreeNode<T> *Parent(BinTreeNode<T> *subTree, BinTreeNode<T> *current);
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));
bool IsBalanced(BinTreeNode<T> *subTree, int &height);
friend istream &operator>>(istream &in, BinaryTree<T> &Tree)
{
Tree.CreateBinTree(in, Tree.root);
return in;
};
friend ostream &operator<<(ostream &out, BinaryTree<T> &Tree)
{
//输出二叉树
Tree.Traverse(Tree.root, out);
out << endl;
return out;
};
friend int operator==(const BinaryTree<T> &s, const BinaryTree<T> &t)
{
return equal(s.root, t.root) ? true : false;
};
//public:
//void MakeTree(const T item,BinaryTree<T> &left,BinaryTree<T>& right);
//void PrintBTree(BinTreeNode<T> *BT,int level);
};
template <class T>
BinTreeNode<T> *BinaryTree<T>::Insert(BinTreeNode<T> *curr, const T &x, int d)
{ /*在二叉树的curr结点左/右插入新子女结点x原来的子女节点作为新结点的子女结点。d=0左插入d不等于0右插入。插入成功返回新子女结点的地址。*/
//在这里添加你的程序替换下面的语句完成任务1实现在curr结点左/右插入子女结点x。
auto node = new BinTreeNode<T>(x);
node->leftChild = curr->leftChild;
node->rightChild = curr->rightChild;
if (d == 0)
curr->leftChild = node, curr->rightChild = nullptr;
else
curr->leftChild = nullptr, curr->rightChild = node;
return node;
}
template <class T>
BinTreeNode<T> *BinaryTree<T>::Find(BinTreeNode<T> *subtree, const T &x) const
{ //私有函数在以subtree为根的二叉树中查找x查找成功返回结点地址否则返回0。
//在这里添加你的程序替换下面的语句完成任务2实现在以subtree为根的二叉树中递归搜索结点x。
if (subtree == nullptr) return nullptr;
if (x == subtree->data) return subtree;
if (x < subtree->data) return Find(subtree->leftChild, x);
if (x > subtree->data) return Find(subtree->rightChild, x);
return NULL;
}
template <class T>
void BinaryTree<T>::destroy(BinTreeNode<T> *&subTree)
{ // 私有函数若指针subTree不为空则删除根为subTree的子树
if (subTree != NULL)
{
destroy(subTree->leftChild);
destroy(subTree->rightChild);
delete subTree;
subTree = NULL;
}
}
template <class T>
BinTreeNode<T> *BinaryTree<T>::Parent(BinTreeNode<T> *subTree, BinTreeNode<T> *current)
{ // 私有函数从结点subTree开始搜索结点current的父节点若找到结点current的父节点则函数返回父结点地址否则返回NULL
if (subTree == NULL) return NULL;
if (subTree->leftChild == current || subTree->rightChild == current)
return subTree;
BinTreeNode<T> *p = Parent(subTree->leftChild, current);
if (p != NULL)
return p;
else
return Parent(subTree->rightChild, current);
}
template <class T>
void BinaryTree<T>::Traverse(BinTreeNode<T> *subTree, ostream &out)
{
if (subTree != NULL)
{
out << subTree->data << " ";
Traverse(subTree->leftChild, out);
Traverse(subTree->rightChild, out);
}
}
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);
}
}
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);
}
}
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);
}
}
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) const
{
if (subTree == NULL)
return 0;
else
{
int i = Height(subTree->leftChild);
int j = Height(subTree->rightChild);
return (i < j) ? j + 1 : i + 1;
}
}
template <class T>
BinaryTree<T>::BinaryTree(BinaryTree<T> &s)
{
root = Copy(s.getRoot());
RefValue = s.RefValue;
}
template <class T>
BinTreeNode<T> *BinaryTree<T>::Copy(BinTreeNode<T> *orignode)
{
if (orignode == NULL) return NULL;
BinTreeNode<T> *temp = new BinTreeNode<T>;
temp->data = orignode->data;
temp->leftChild = Copy(orignode->leftChild);
temp->rightChild = Copy(orignode->rightChild);
return temp;
}
template <class T>
void BinaryTree<T>::CreateBinTree(istream &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;
}
}
template <class T>
int BinaryTree<T>::NonR_Height()
{
//在这里添加你的程序替换下列语句完成任务4使用非递归方法求二叉树的高度。空树高度为0.
queue<pair<BinTreeNode<T> *, int>> Q;
int ans = 0;
for (Q.push(make_pair(this->root, this->root != nullptr)); !Q.empty(); Q.pop())
{
auto cur = Q.front();
ans = max(ans, cur.second);
if (cur.first->leftChild) Q.push(make_pair(cur.first->leftChild, cur.second + 1));
if (cur.first->rightChild) Q.push(make_pair(cur.first->rightChild, cur.second + 1));
}
return ans;
}
template <class T>
bool BinaryTree<T>::IsBalanced(BinTreeNode<T> *subTree, int &height)
{ //如果每个结点的左子树和右子树的高度差的绝对值都小于2则二叉树是平衡的。subTree二叉树如果是平衡的则返回true否则返回false。
//subTree二叉树的高度通过形参height返回。
//在这里添加你的程序替换下面的语句完成任务3编写递归算法实现判断二叉树是否为平衡二叉树。
if (subTree == nullptr) return height = 0, true;
int hl = 0, hr = 0;
bool flag = true;
if (flag) flag = flag && IsBalanced(subTree->leftChild, hl);
if (flag) flag = flag && IsBalanced(subTree->rightChild, hr);
if (flag) flag = flag && abs(hr - hl) < 2;
return flag;
}
template <class T>
void BinaryTree<T>::NonR_preOrder(void (*visit)(BinTreeNode<T> *p)) //非递归前序遍历
{
SeqStack<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);
if (p->leftChild != NULL)
S.Push(p->leftChild);
}
}
template <class T>
void BinaryTree<T>::NonR_preOrder1(void (*visit)(BinTreeNode<T> *p)) //非递归前序遍历
{
SeqStack<BinTreeNode<T> *> S;
BinTreeNode<T> *p = root;
S.Push(NULL);
while (p != NULL)
{
visit(p);
if (p->rightChild != NULL)
S.Push(p->rightChild);
if (p->leftChild != NULL)
p = p->leftChild;
else
S.Pop(p);
}
}
template <class T>
void BinaryTree<T>::NonR_inOrder(void (*visit)(BinTreeNode<T> *p)) //非递归中序遍历
{
SeqStack<BinTreeNode<T> *> S;
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());
}
template <typename T>
struct stkNode
{
BinTreeNode<T> *ptr; //树结点指针
enum
{
L,
R
} tag; //退栈标记必须说明为枚举变量tag移到最右边。这里最好用bool量
stkNode(BinTreeNode<T> *N = NULL)
{
ptr = N;
tag = L;
} //构造函数
};
template <class T>
void BinaryTree<T>::NonR_postOrder(void (*visit)(BinTreeNode<T> *p)) //非递归后序遍历
{
LinkedStack<stkNode<T>> S;
stkNode<T> w;
BinTreeNode<T> *p = root; //p是遍历指针
do
{
while (p != NULL)
{
w.ptr = p;
w.tag = stkNode<T>::L; //枚举类型定义在struct stkNode中如定义为全局性就简单了
S.Push(w);
p = p->leftChild;
}
int continue1 = 1; //继续循环标记, 用于R
while (continue1 && !S.IsEmpty())
{
S.Pop(w);
p = w.ptr;
switch (w.tag)
{ //判断栈顶的tag标记
case stkNode<T>::L:
w.tag = stkNode<T>::R;
S.Push(w);
continue1 = 0;
p = p->rightChild;
break;
case stkNode<T>::R: visit(p); break;
}
}
} while (!S.IsEmpty()); //继续遍历其他结点
cout << endl;
}
template <class T>
void BinaryTree<T>::levelOrder(void (*visit)(BinTreeNode<T> *p)) //非递归层序遍历
{
SeqQueue<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);
}
}
template <class T>
bool equal(BinTreeNode<T> *a, BinTreeNode<T> *b)
{
if (a == NULL && b == NULL)
return true;
if (a != NULL && b != NULL && a->data == b->data && equal(a->leftChild, b->leftChild) && equal(a->rightChild, b->rightChild))
{
//cout << a->data << endl;cout << b->data << endl;
return true;
}
else
{
return false;
}
}
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 << ')';
}
else if (BT->leftChild == NULL && BT->rightChild == NULL)
{
cout << '(';
cout << ',';
cout << ')';
}
}
}
template <class T>
void PrintBTree(BinTreeNode<T> *BT, int level)
{ //以凹入表形式输出二叉树
if (BT != NULL) //如果二叉树不空
{
//二叉树root->Right()第level+1层结点数据域值的横向显示
PrintBTree(BT->rightChild, level + 1);
if (level != 0)
{
//走过6*(level-1)个空格
for (int i = 0; i < 6 * (level - 1); i++) cout << " ";
cout << "----"; //显示横线----
}
cout << BT->data << endl; //显示结点的数据域值
//二叉树root->Left()第level+1层结点数据域值的横向显示
PrintBTree(BT->leftChild, level + 1);
}
}
#endif