#include "DCirList.h"
#pragma once
#pragma region
//树类
//测试日期 2010-3-11
#ifndef TREENODE_H
#define TREENODE_H
template<class T>
class TreeNode
{
public:
TreeNode<T>* firstchild; //第一个孩子结点指针
TreeNode<T>* nextsibling; //下一个兄弟结点指针
T data; //数据域
TreeNode(){firstchild=nextsibling=NULL;} //构造函数
TreeNode(T item,TreeNode<T>* pf=NULL,TreeNode<T>* pn=NULL) //重载构造函数
{data=item;firstchild=pf;nextsibling=pn;}
};
#endif
#pragma endregion
#pragma region
#ifndef TREE_H
#define TREE_H
template<class T>
class Tree
{
private:
TreeNode<T>* root; //根结点指针
TreeNode<T>* current; //当前结点指针
TreeNode<T>* SearchParent(TreeNode<T>* t,TreeNode<T>* s); //递归查找父结点
TreeNode<T>* SearchPrevious(TreeNode<T>* t,TreeNode<T>* s); //递归查找前驱结点
TreeNode<T>* Copy(TreeNode<T>* t); //拷贝函数
public:
Tree(){root=current=NULL;} //构造函数
~Tree(){ClearTree();} //析构函数
void ClearTree(){DeleteSubtree(root);} //清空树
//获取结点指针(8个函数)
TreeNode<T>* GetRoot()
{return root;} //返回根结点指针
TreeNode<T>* GetCurrent()
{return current;} //返回当前结点指针
TreeNode<T>* GetParent(); //返回当前结点的父结点的指针
TreeNode<T>* GetPrevious(); //返回当前结点的前驱结点的指针
TreeNode<T>* GetFirstChild() //返回当前结点的第一个孩子结点的指针
{return current==NULL?NULL:current->firstchild;}
TreeNode<T>* GetLastChild(); //返回当前结点的最后一个孩子结点的指针
TreeNode<T>* GetNextSibling() //返回当前结点的兄弟结点的指针
{return current==NULL?NULL:current->nextsibling;}
TreeNode<T>* GetChild(int i); //返回当前结点的第i个孩子结点的指针
//三种遍历(3个函数)
void PreOrder(TreeNode<T> *t,void(*visit)(T x)); //先根遍历以t为根结点的数据域
void PosOrder(TreeNode<T> *t,void(*visit)(T x)); //后根遍历以t为根结点的数据域
void LevelOrder(TreeNode<T> *t,void(*visit)(T x)); //层序遍历以t为根结点的数据域
//设置当前结点,并返回当前结点指针(8个函数)
TreeNode<T>* SetRoot()
{return current=root;} //把根结点设置为当前结点
TreeNode<T>* SetCurrent(TreeNode<T> *t)
{return current=t;} //把t所指向的结点设置为当前结点
TreeNode<T>* SetParent()
{return current=GetParent();} //把当前结点的父结点设置为当前结点
TreeNode<T>* SetPrevious()
{return current=GetPrevious();} //把当前结点的前驱结点设置为当前结点
TreeNode<T>* SetFirstChild()
{return current=GetFirstChild();} //把当前结点的第一个孩子结点设置为当前结点
TreeNode<T>* SetLastChild()
{return current=GetLastChild();} //把当前结点的最后一个孩子结点设置为当前结点
TreeNode<T>* SetNextSibling()
{return current=GetNextSibling();} //把当前结点的兄弟结点设置为当前结点
TreeNode<T>* SetChild(int i)
{return current=GetChild(i);} //把当前结点的第i个孩子结点设置为当前结点
//插入与删除(6个函数)
void InsertFirstChild(T x); //把x插入为当前结点的第一个孩子结点
void InsertLastChild(T x); //把x插入为当前结点的最后一个孩子结点
void InsertChild(int i,T x); //把x插入为当前结点的第i个孩子结点
void InsertSibling(T x); //把x插入为当前结点的下一个兄弟结点
void DeleteSubtree(TreeNode<T>* &t); //删除以t为根结点的子树
void DeleteChild(int i); //删除当前结点的第i个孩子结点
//其他操作(2个函数)
bool IsEmpty(){return root==NULL?true:false;} //判断是否为空树
Tree<T>& operator=(Tree<T>& tree); //运算符重载
};
#endif
#pragma endregion
#pragma region
template<class T>
TreeNode<T>* Tree<T>::SearchParent(TreeNode<T> *t, TreeNode<T> *s)
{
if(t==NULL||s==NULL||s==root) return NULL;
TreeNode<T>* p=t->firstchild;
for(;p!=NULL;p=p->nextsibling)
{
if(p==s) return t;
SearchParent(p,s);
}
return NULL;
}
template<class T>
TreeNode<T>* Tree<T>::SearchPrevious(TreeNode<T> *t, TreeNode<T> *s)
{
if(t==NULL||s==NULL||s==root) return NULL;
if(t->firstchild==s||t->nextsibling==s) return t;
TreeNode<T> *p=NULL;
if((p=SearchPrevious(t->firstchild,s))!=NULL) return p;
if((p=SearchPrevious(t->nextsibling,s))!=NULL) return p;
}
template<class T>
TreeNode<T>* Tree<T>::Copy(TreeNode<T> *t)
{
if(t==NULL) return NULL;
TreeNode<T>* p=new TreeNode<T>();
p->data=t->data;
p->firstchild=Copy(t->firstchild);
p->nextsibling=Copy(t->nextsibling);
return p;
}
template<class T>
TreeNode<T>* Tree<T>::GetParent()
{
return SearchParent(root,current);
}
template<class T>
TreeNode<T>* Tree<T>::GetPrevious()
{
return SearchPrevious(root,current);
}
template<class T>
TreeNode<T>* Tree<T>::GetLastChild()
{
if(current==NULL) return NULL;
TreeNode<T>* p=current->firstchild;
for(;p->nextsibling!=NULL;p=p->nextsibling);
return p;
}
template<class T>
TreeNode<T>* Tree<T>::GetChild(int i)
{
if(current==NULL||i<0) return NULL;
TreeNode<T>* p=current->firstchild;
for(int k=0;p!=NULL&&k<i;k++)
p=p->nextsibling;
return p;
}
template<class T>
void Tree<T>::PreOrder(TreeNode<T> *t, void (*visit)(T))
{
if(t==NULL) return;
visit(t->data);
if(t->firstchild!=NULL) PreOrder(t->firstchild,visit);
if(t->nextsibling!=NULL) PreOrder(t->nextsibling,visit);
}
template<class T>
void Tree<T>::PosOrder(TreeNode<T> *t, void (*visit)(T))
{
if(t==NULL) return;
if(t->firstchild!=NULL) PosOrder(t->firstchild,visit);
visit(t->data);
if(t->nextsibling!=NULL) PosOrder(t->nextsibling,visit);
}
template<class T>
void Tree<T>::LevelOrder(TreeNode<T> *t, void (*visit)(T))
{
if(t==NULL) return;
DCirList<TreeNode<T>*> list;
TreeNode<T>* p1,*p2;
list.PushBack(t);
while(!list.IsEmpty())
{
p1=list.PopFront();
visit(p1->data);
p2=p1->firstchild;
while(p2!=NULL)
{
list.PushBack(p2);
p2=p2->nextsibling;
}
}
}
template<class T>
void Tree<T>::InsertFirstChild(T x)
{
TreeNode<T>* newnode=new TreeNode<T>(x);
if(root==NULL){current=root=newnode; return;}
if(current==NULL)return;
if(current->firstchild!=NULL)
{
TreeNode<T>* p=GetFirstChild();
current->firstchild=newnode;
newnode->nextsibling=p;
}
else
current->firstchild=newnode;
}
template<class T>
void Tree<T>::InsertLastChild(T x)
{
TreeNode<T>* newnode=new TreeNode<T>(x);
if(root==NULL){current=root=newnode; return;}
if(current==NULL)return;
if(current->firstchild!=NULL)
{
TreeNode<T>* p=GetLastChild();
p->nextsibling=newnode;
}
else
current->firstchild=newnode;
}
template<class T>
void Tree<T>::InsertChild(int i, T x)
{
TreeNode<T>* newnode=new TreeNode<T>(x);
if(root==NULL){current=root=newnode; return;}
if(current==NULL||i<0)return;
TreeNode<T>* p=current->firstchild;
if(p!=NULL)
{
if(i==0)
{
newnode->nextsibling=p;
current->firstchild=newnode;
}
else
{
p=GetChild(i-1);
newnode->nextsibling=p->nextsibling;
p->nextsibling=newnode;
}
}
else
current->firstchild=newnode;
}
template<class T>
void Tree<T>::InsertSibling(T x)
{
if(current==NULL||current==root)return;
TreeNode<T>* newnode=new TreeNode<T>(x);
newnode->nextsibling=current->nextsibling;
current->nextsibling=newnode;
}
template<class T>
void Tree<T>::DeleteSubtree(TreeNode<T>* &t)
{
if(t==NULL) return;
TreeNode<T> *r,*p1,*p2;
p1=t->firstchild;
while(p1!=NULL)
{
p2=p1->nextsibling;
DeleteSubtree(p1);
p1=p2;
}
r=SearchPrevious(root,t);
if(r!=NULL)
{
if(r->firstchild==t)
r->firstchild=t->nextsibling;
if(r->nextsibling==t)
r->nextsibling=t->nextsibling;
}
delete t;
t=NULL;
}
template<class T>
void Tree<T>::DeleteChild(int i)
{
TreeNode<T>* p=GetChild(i);
DeleteSubtree(p);
}
template<class T>
Tree<T>& Tree<T>::operator =(Tree<T> &tree)
{
if(tree.root==NULL) return *this;
current=root=Copy(tree.root);
return *this;
}
#pragma endregion
分享到:
相关推荐
《数据结构》课程中的树是一种重要的非线性数据结构,...理解并掌握树的这些概念和操作对于学习数据结构和算法至关重要,因为树在计算机科学的许多领域,如文件系统、编译器设计、图形学和数据库中都有着广泛的应用。
本资源"树的孩子兄弟表示法代码.rar"提供了一种特殊的树存储方法——孩子兄弟表示法,用C++语言实现,并已通过调试。这种表示法对初学者来说是很有价值的学习材料,特别是对于正在学习数据结构入门阶段的同学。 ...
- 在树 T 中,如果 Y 是 X 的右孩子,则 X 和 Y 是兄弟关系。 - 二叉树 R 的根结点的右子树无法直接确定。 **7. 线性表的插入操作** - 插入操作的平均移动元素次数取决于插入的位置。 - 计算公式为 \(\frac{2n - 1}...
用于数据结构二叉树学习,体会递归思想的妙用。
孩子兄弟树,也被称为双链树,是一种特殊的数据结构,它在计算机科学中主要用于表示具有多个子节点的树形结构。这种数据结构扩展了传统的二叉树,每个节点不仅有一个左孩子和一个右孩子,还可以有任意数量的中间孩子...
每种方法都有其优缺点,例如双亲表示法查找父节点快速但查找子节点较慢,孩子兄弟表示法则可以将树转换为二叉树,便于利用二叉树的操作。 最后,森林的遍历类似于单棵树的遍历,但涉及到多棵树的情况。森林的先序...
【数据结构:树和二叉树】 树是一种非线性的数据结构,它的基本概念和术语在计算机科学中至关重要,尤其在算法设计和数据组织中扮演着核心角色。树的定义基于递归,一棵非空树包含一个根节点,以及一组互不相交的...
本压缩包文件“Trees”包含了用C#实现的树数据结构的源代码,这对于学习和理解数据结构以及C#编程是非常有价值的。 树是一种非线性数据结构,由节点(也称为顶点)和边组成,每个节点可以有零个或多个子节点。在C#...
【二叉树】是数据结构中的重要组成部分,它是一种特殊的树结构,每个节点最多只有两个子节点,分别称为左子节点和右子节点。二叉树的概念有助于解决许多计算机科学中的问题,例如文件系统目录结构的表示、搜索算法的...
树的存储结构包括双亲数组表示法、孩子链表表示法、左孩子右兄弟表示法等。双亲数组表示法是一种存储表示树结构的方法,它通过一个一维数组来存储树中所有结点的信息及其双亲信息,数组中的每个元素代表一个结点,...
数据结构中的树是一种重要的非线性数据结构,它模拟了现实世界中许多组织关系,例如家族树、组织架构等。树形结构在计算机科学中有着广泛的应用,如编译器的语法分析、数据库的索引结构等。在这个实验报告中,我们将...
- **左孩子-右兄弟表示法**:每个节点包含其左孩子和右兄弟节点的引用。 4. **树的运算** - **遍历**:主要有前序遍历、中序遍历和后序遍历,用于访问树的所有节点。 - **线索二叉树**:在二叉树中加入线索,...
在计算机科学中,树是一种重要的非线性数据结构,它能够有效地表示和处理具有层次关系的数据。在专升本数据结构的学习中,理解树的概念、性质和操作至关重要。本章主要涵盖以下几个方面: 1. **树的定义**: 树是...
此外,还有左孩子右兄弟表示法,其中每个节点的右兄弟是其父节点的下一个孩子,这种表示法在某些操作中简化了代码实现。 二叉树的基本特征是每个节点最多有两个子节点,这导致了一些独特的性质。例如,第i层的最大...
首先,树是一种非线性的数据结构,以分支关系表示层次结构。在树中,有一个特殊的节点称为根节点,它没有前驱节点,而其他节点可以分为若干互不相交的子树,每个子树自身也是一棵树。树的特点是至少有一个节点(根...
树的存储结构是指树在计算机中的表示方式,包括双亲表示法、孩子表示法、双亲孩子表示法、孩子兄弟表示法等。树的基本操作包括树的创建、树的遍历、树的查找、树的插入、树的删除等。 二叉树是特殊类型的树,具有...
5. 双法表示树类(如孩子双亲表示树、孩子兄弟表示树): - `ElemType data`:节点的数据域。 - `int parent` 或 `LinkList<int>childLkList`:表示父节点或子节点的链接。 - `int parent` 或 `...
### 数据结构教程与题解 —— 树形结构章节知识点详解 #### 一、树形结构概述 **树形结构**是一种重要的非线性数据结构,用于描述数据元素之间的一对多逻辑关系。这种结构中的节点形成分支和层次关系,类似于自然...