#include "Common.h"
#include "DCirList.h"
#pragma once
#pragma region
//二叉树类
//测试日期 2010-3-13
#ifndef BINTREENODE_H
#define BINTREENODE_H
template<class T>
class BinTreeNode
{
public:
BinTreeNode<T>* leftchild;
BinTreeNode<T>* rightchild;
T data;
BinTreeNode(){leftchild=rightchild=NULL;} //默认构造函数
BinTreeNode(T item,BinTreeNode<T>* pl=NULL,BinTreeNode<T>* pr=NULL) //重载构造函数
{data=item;leftchild=pl;rightchild=pr;}
};
#endif
#ifndef BINTREE_H
#define BINTREE_H
template<class T>
void _visit(BinTreeNode<T>* x){}
template<class T>
class BinTree
{
protected:
BinTreeNode<T>* root; //二叉树根结点指针
BinTreeNode<T>* current; //二叉树当前结点指针
DCirList<BinTreeNode<T>*> L; //遍历链表
//[3个函数]
BinTreeNode<T>* Copy(BinTreeNode<T>* t); //复制二叉树
BinTreeNode<T>* CreateBinTree(T *VLR,T *LVR,int n); //由VLR,LVR序列创建二叉树
BinTreeNode<T>* SearchParent(BinTreeNode<T>* t,BinTreeNode<T>* s); //在二叉树t中回溯查找s的父结点
public:
BinTree(){root=current=NULL;} //构造函数
~BinTree(){ClearTree();} //析构函数
void ClearList(){L.ClearList();} //清空遍历表
//[4个函数]
BinTree<T>& CreateBinTree(DCirList<T> vlr, DCirList<T> lvr); //由VLR,LVR序列创建二叉树
void ClearTree(){DeleteSubTree(root);} //清空二叉树
int TreeSize(BinTreeNode<T>* t); //返回以t为根结点的二叉树的结点个数
int TreeSize(){return TreeSize(root);} //二叉树的结点数
//获取结点指针[6个函数]
BinTreeNode<T>* GetRoot(){return root;} //返回根结点指针
BinTreeNode<T>* GetCurrent(){return current;} //返回当前结点指针
BinTreeNode<T>* GetParent(){return SearchParent(root,current);} //返回当前结点的父结点指针
BinTreeNode<T>* GetLeftChild(); //返回当前结点的左孩子结点指针
BinTreeNode<T>* GetRightChild(); //返回当前结点的右孩子结点指针
BinTreeNode<T>* GetSibling(); //返回当前结点的兄弟结点指针
//四种遍历[8个函数]
void PreOrderTree(BinTreeNode<T>* t,void(*visit)(BinTreeNode<T>* x)); //前序遍历以t为根结点的数据域
DCirList<BinTreeNode<T>*> GetPreList(BinTreeNode<T>* t);
void InOrderTree(BinTreeNode<T>* t,void(*visit)(BinTreeNode<T>* x)); //中序遍历以t为根结点的数据域
DCirList<BinTreeNode<T>*> GetInList(BinTreeNode<T>* t);
void PosOrderTree(BinTreeNode<T>* t,void(*visit)(BinTreeNode<T>* x)); //后序遍历以t为根结点的数据域
DCirList<BinTreeNode<T>*> GetPosList(BinTreeNode<T>* t);
void LevelOrderTree(BinTreeNode<T>* t,void(*visit)(BinTreeNode<T>* x)); //层序遍历以t为根结点的数据域
DCirList<BinTreeNode<T>*> GetLevelList(BinTreeNode<T>* t);
//设置当前结点并返回当前结点指针[7个函数]
BinTreeNode<T>* SetRoot(){return current=root;} //把根结点设置为当前结点
BinTreeNode<T>* SetCurrent(BinTreeNode<T>* t){return current=t;} //把t所指向的结点设置为当前结点
BinTreeNode<T>* SetCurrent(char* p); //设置当前节点,如p='lrlrlr';l代表左,r代表右
BinTreeNode<T>* SetParent(){return current=GetParent();} //把当前结点的父结点设置为当前结点
BinTreeNode<T>* SetLeftChild(){return current=GetLeftChild();} //把当前结点的左孩子结点设置为当前结点
BinTreeNode<T>* SetRightChild(){return current=GetRightChild();} //把当前结点的右孩子结点设置为当前结点
BinTreeNode<T>* SetSibling(){return current=GetSibling();} //把当前结点的兄弟结点设置为当前结点
//插入删除操作[7个函数]
void InsertLeftChild(T x); //把x插入为当前结点的左孩子结点
void InsertRightChild(T x); //把x插入为当前结点的右孩子结点
void InsertLeftTree(BinTree<T> &tree); //把tree插入为当前结点的左孩子树[原孩子树被替换]
void InsertRightTree(BinTree<T> &tree); //把tree插入为当前结点的右孩子树[原孩子树被替换]
void DeleteLeftChild(); //删除当前结点的左孩子结点
void DeleteRightChild(); //删除当前结点的右孩子结点
void DeleteSubTree(BinTreeNode<T>* &t); //删除以t为根结点的子树
//其他4个函数
bool IsLeaf(); //判断当前结点是否为叶子结点
int Depth(BinTreeNode<T>* t); //返回以t为根结点的二叉树的深度
int LeafCount(BinTreeNode<T>* t); //返回以t为根节点的二叉树的叶子的个数
BinTree<T>& operator=(BinTree<T>& t);
};
#endif
template<class T>
BinTreeNode<T>* BinTree<T>::Copy(BinTreeNode<T> *t)
{
if(t==NULL)
return NULL;
BinTreeNode<T>* p=new BinTreeNode<T>;
p->data=t->data;
if(t->leftchild!=NULL)
p->leftchild=Copy(t->leftchild);
if(t->rightchild!=NULL)
p->rightchild=Copy(t->rightchild);
return p;
}
template<class T>
BinTreeNode<T>* BinTree<T>::CreateBinTree(T *VLR, T *LVR, int n)
{
if(n==0)
return NULL;
int k=0;
while(k<n&&VLR[0]!=LVR[k])
k++;
BinTreeNode<T> *t=new BinTreeNode<T>(VLR[0]);
t->leftchild=CreateBinTree(VLR+1,LVR,k);
t->rightchild=CreateBinTree(VLR+k+1,LVR+k+1,n-k-1);
return t;
}
template<class T>
BinTreeNode<T>* BinTree<T>::SearchParent(BinTreeNode<T> *t, BinTreeNode<T> *s)
{
if(t==NULL||s==NULL||s==root)
return NULL;
if(t->leftchild==s||t->rightchild==s)
return t;
BinTreeNode<T> *p;
if((p=SearchParent(t->leftchild,s))!=NULL)
return p;
if((p=SearchParent(t->rightchild,s))!=NULL)
return p;
}
template<class T>
BinTree<T>& BinTree<T>::CreateBinTree(DCirList<T> vlr, DCirList<T> lvr)
{
int n=vlr.Size();
if(n!=lvr.Size()){root=NULL;return *this;}
T* VLR=new T[n];
T* LVR=new T[n];
for(int i=0;i<n;i++)
{
VLR[i]=vlr.GetData(i);
LVR[i]=lvr.GetData(i);
}
current=root=CreateBinTree(VLR,LVR,n);
delete VLR;
delete LVR;
return *this;
}
template<class T>
int BinTree<T>::TreeSize(BinTreeNode<T>* t)
{
if(t==NULL)
return 0;
else
return 1+TreeSize(t->leftchild)+TreeSize(t->rightchild);
}
template<class T>
BinTreeNode<T>* BinTree<T>::GetLeftChild()
{
return current==NULL?NULL:current->leftchild;
}
template<class T>
BinTreeNode<T>* BinTree<T>::GetRightChild()
{
return current==NULL?NULL:current->rightchild;
}
template<class T>
BinTreeNode<T>* BinTree<T>::GetSibling()
{
if(current=root||current==NULL)
return NULL;
BinTreeNode<T> *p;
p=GetParent();
if(p1->leftchild==current)
return p->rightchild;
else
return p->leftchild;
}
template<class T>
void BinTree<T>::PreOrderTree(BinTreeNode<T> *t, void (*visit)(BinTreeNode<T>* x))
{
if(t==NULL)
return;
visit(t); L.PushBack(t);
if(t->leftchild!=NULL)
PreOrderTree(t->leftchild,visit);
if(t->rightchild!=NULL)
PreOrderTree(t->rightchild,visit);
}
template<class T>
DCirList<BinTreeNode<T>*> BinTree<T>::GetPreList(BinTreeNode<T> *t)
{
ClearList();
PreOrderTree(t,_visit);
return L;
}
template<class T>
void BinTree<T>::InOrderTree(BinTreeNode<T> *t, void (*visit)(BinTreeNode<T>* x))
{
if(t==NULL)
return;
if(t->leftchild!=NULL)
InOrderTree(t->leftchild,visit);
visit(t); L.PushBack(t);
if(t->rightchild!=NULL)
InOrderTree(t->rightchild,visit);
}
template<class T>
DCirList<BinTreeNode<T>*> BinTree<T>::GetInList(BinTreeNode<T> *t)
{
ClearList();
InOrderTree(t,_visit);
return L;
}
template<class T>
void BinTree<T>::PosOrderTree(BinTreeNode<T> *t, void (*visit)(BinTreeNode<T>* x))
{
if(t==NULL)
return;
if(t->leftchild!=NULL)
PosOrderTree(t->leftchild,visit);
if(t->rightchild!=NULL)
PosOrderTree(t->rightchild,visit);
visit(t); L.PushBack(t);
}
template<class T>
DCirList<BinTreeNode<T>*> BinTree<T>::GetPosList(BinTreeNode<T> *t)
{
ClearList();
PosOrderTree(t,_visit);
return L;
}
template<class T>
void BinTree<T>::LevelOrderTree(BinTreeNode<T> *t, void (*visit)(BinTreeNode<T>* x))
{
if(t==NULL)
return;
DCirList<BinTreeNode<T>* >q;
BinTreeNode<T> *p;
q.PushBack(t);
while(!q.IsEmpty())
{
p=q.PopFront();
visit(p); L.PushBack(p);
if(p->leftchild!=NULL) q.EnterQueue(p->leftchild);
if(p->rightchild!=NULL) q.EnterQueue(p->rightchild);
}
}
template<class T>
DCirList<BinTreeNode<T>*> BinTree<T>::GetLevelList(BinTreeNode<T> *t)
{
ClearList();
LevelOrderTree(t,_visit);
return L;
}
template<class T>
BinTreeNode<T>* BinTree<T>::SetCurrent(char *p)
{
current=root;
int n=strlen(p);
for(int i=0;i<n;i++)
{
if(p[i]=='l')
SetLeftChild();
if(p[i]=='r')
SetRightChild();
}
return current;
}
template<class T>
void BinTree<T>::InsertLeftChild(T x)
{
BinTreeNode<T> *newnode=new BinTreeNode<T>(x);
if(root==NULL){root=current=newnode;return;}
if(current==NULL)return;
newnode->leftchild=current->leftchild;
current->leftchild=newnode;
}
template<class T>
void BinTree<T>::InsertRightChild(T x)
{
BinTreeNode<T> *newnode=new BinTreeNode<T>(x);
if(root==NULL){root=current=newnode;return;}
if(current==NULL)return;
newnode->rightchild=current->rightchild;
current->rightchild=newnode;
}
template<class T>
void BinTree<T>::InsertLeftTree(BinTree<T> &tree)
{
BinTreeNode<T>* p=Copy(tree.root);
DeleteLeftChild();
current->leftchild=p;
}
template<class T>
void BinTree<T>::InsertRightTree(BinTree<T> &tree)
{
BinTreeNode<T>* p=Copy(tree.root);
DeleteRightChild();
current->rightchild=p;
}
template<class T>
void BinTree<T>::DeleteLeftChild()
{
DeleteSubTree(current->leftchild);
}
template<class T>
void BinTree<T>::DeleteRightChild()
{
DeleteSubTree(current->rightchild);
}
template<class T>
void BinTree<T>::DeleteSubTree(BinTreeNode<T> *&t)
{
if(t==NULL) return;
if(t->leftchild!=NULL)
DeleteSubTree(t->leftchild);
if(t->rightchild!=NULL)
DeleteSubTree(t->rightchild);
BinTreeNode<T> *p=SearchParent(root,t);
if(p!=NULL)
{
if(p->leftchild==t)
p->leftchild=NULL;
if(p->rightchild==t)
p->rightchild=NULL;
}
delete t;
t=NULL;
}
template<class T>
bool BinTree<T>::IsLeaf()
{
if(current==NULL)
return false;
return (current->leftchild==NULL&¤t->rightchild==NULL);
}
template<class T>
int BinTree<T>::Depth(BinTreeNode<T>* t)
{
if(t==NULL)
return 0;
int ldep=Depth(t->leftchild);
int rdep=Depth(t->rightchild);
return ldep>rdep?ldep+1:rdep+1;
}
template<class T>
int BinTree<T>::LeafCount(BinTreeNode<T>* t)
{
int count=0;
if(t!=NULL)
{
count+=CountLeaf(t->leftchild);
count+=CountLeaf(t->rightchild);
if(t->leftchild==NULL&&t->rightchild==NULL)
count++;
}
return count;
}
template<class T>
BinTree<T>& BinTree<T>::operator =(BinTree<T> &t)
{
current=root=Copy(t.root);
return *this;
}
分享到:
相关推荐
"数据结构--二叉树--思维导图" 二叉树是一种常见的数据结构,它是一种树形结构,每个节点最多有两个孩子节点,分别是左子树和右子树。二叉树可以用来存储大量数据,并且可以快速地查找、插入和删除数据。 二叉树的...
通过学习和实践这个主题,不仅可以提高对二叉树操作的熟练度,还能为理解其他高级数据结构和算法打下坚实的基础。在实际的软件开发中,理解并能灵活运用线索化二叉树可以帮助优化复杂数据的处理,提高程序运行效率。
理解并掌握这些二叉树的概念和性质对于学习数据结构和算法至关重要,它们是许多复杂问题解决方案的基础,比如搜索、排序、压缩等。通过深入学习和实践,可以更好地应用二叉树来解决实际的计算问题。
总的来说,这个程序涵盖了二叉树的基本操作,包括构造、遍历和释放,是学习二叉树及其应用的一个典型实例。通过这个程序,我们可以深入理解二叉树的链式存储结构和遍历算法,这对于后续学习其他复杂的数据结构和算法...
在IT领域,数据结构是计算机科学的基础,而二叉树作为一种重要的数据结构,广泛应用于算法设计、数据库系统、编译器等。本资料主要聚焦于使用C++语言实现二叉树的遍历方法,这对于理解和掌握C++编程以及数据结构至关...
"算法大全-面试题-链表-栈-二叉树-数据结构"这个压缩包文件提供了丰富的知识资源,旨在帮助学习者深入理解和应用这些核心概念。 链表是一种线性数据结构,与数组不同,它的元素在内存中不是连续存储的。链表由一...
二叉树是计算机科学中数据结构的一个重要概念,它在许多算法和问题解决中发挥着核心作用。在数据结构的世界里,二叉树是一种特殊的树形结构,其中每个节点最多有两个子节点,通常称为左子节点和右子节点。这种结构...
理解并掌握二叉树的遍历对于学习数据结构和算法至关重要,因为它是许多高级概念的基础,如树的搜索、复制和压缩存储等。在实际应用中,二叉树遍历也常用于解析XML文档、编译器符号表管理以及数据库索引等场景。因此...
平衡二叉树(Balanced Binary Tree)是数据结构中的一个重要概念,尤其在算法设计和数据库系统中发挥着关键作用。本实验是针对广东工业大学(简称“广工”)学生的一次数据结构课程实践,旨在让学生深入理解平衡...
通过编写和调试这些代码,我们可以深入学习二叉树的特性和算法,并提高解决问题的能力。在学习和实践中,可以结合《数据结构》课本 严蔚敏 吴伟民编著 清华大学出版社的内容,以理论与实践相结合的方式,更有效地...
在IT领域,数据结构是计算机...对于深入学习,可以参考给定的文档“常用数据结构--线性结构&二叉树.docx”,它可能包含了更多关于线性结构和二叉树的详细信息,包括示例代码和实例解析,帮助你更好地掌握这些关键知识。
实验中涉及的算法和操作都是二叉树基本操作的经典实例,对于学习数据结构和算法的初学者来说,这是很好的实践和理解机会。通过这些操作,学生不仅可以深入理解二叉树的性质,还能提升他们在实际问题中应用数据结构的...
前言 在此之前我们学习了二叉树的定义和储存方式,还学了一种特殊的二叉树---堆,那今天我们就正式开始去学习二叉树了,是通过链式结构储存的二叉树,下面我会详细讲解二叉树的创建和遍历方法。相关链接 二叉树的...
二叉树是计算机科学中一种重要的数据结构...综上所述,二叉树是数据结构中的重要组成部分,理解其基本概念、实现方式和遍历方法是深入学习算法和数据结构的关键。通过实践和掌握这些知识,可以有效地解决各种计算问题。
用于数据结构二叉树学习,体会递归思想的妙用。
本实验“广东工业大学数据结构实验-二叉树抽象数据类型”旨在深入理解和应用二叉树这一重要数据结构。二叉树是一种特殊的树形数据结构,每个节点最多有两个子节点,通常分为左子节点和右子节点。吴伟民老师的课程将...
11. 心得体会:通过本次课程设计,学生可以学到递归创建和非递归创建二叉树等有关二叉树的基本知识,并提高动手能力和学习数据结构的能力。 12. 数据结构的重要性:数据结构是计算机科学和信息技术的基础,学习数据...
《数据结构实验-二叉树基本操作概论》是一份关于二叉树算法实现的大学实验报告,旨在帮助学生深入理解和掌握二叉树的构建、存储以及遍历方法。二叉树是计算机科学中一种重要的数据结构,尤其在解决搜索、排序等问题...
通过阅读和理解`BinaryTreeDemo`的代码,你可以深入学习二叉树的JAVA实现。 总结来说,理解和掌握二叉树以及如何用JAVA实现它们是成为优秀程序员的关键一步。通过实践,你可以更深入地了解数据结构的精髓,提升算法...