C++实现树的基本操作,界面友好,操作方便,运行流畅,运用模板
Ⅰ.说明: .采用左孩子右兄弟的方式,转化为二叉树来实现。 .树的后根遍历与二叉树的中根遍历即有联系又有区别,请读者注意分析体会。 Ⅱ.功能: .创建树并写入数据 .先根遍历树 .计算树高 .后根遍历树 .层次遍历树 .搜索数据域为某值的结点 .删除数据域为某值的结点及其子树 .销毁树 Ⅲ.代码: //.h文件 #ifndef TREE_H
#define TREE_H #include<iostream>
#include<iomanip>
using namespace std; template<typename T> //树结点
struct Node
{
T data;
Node<T> *left, *right;
Node(const T& item);
}; template<typename T> //树结点初始化
Node<T>::Node(const T& item)
{
data = item;
left = NULL;
right = NULL;
} template<typename T> //辅助队列,计算树高 Quefh:queue for high
struct Quefh
{
Node<T>* nodrs; //node's adress
int leve; //level
Quefh<T>* hnext;
Quefh(Node<T>* nds, int lel, Quefh<T>* hnxt);
}; template<typename T> //Quefh构造函数
Quefh<T>::Quefh(Node<T>* nds, int lel, Quefh<T>* hnxt)
{
nodrs = nds;
leve = lel;
hnext = hnxt;
} template<typename T> //辅助队列,查找结点 Quefs:queue for search
struct Quefs //此队列同时用于层次遍历
{
Node<T>* snodrs; //Quefs::node's adress
Quefs<T>* snext;
Quefs(Node<T>* snds, Quefs<T>* snxt);
}; template<typename T> //Quefs构造函数
Quefs<T>::Quefs(Node<T>* snds, Quefs<T>* snxt)
{
snodrs = snds;
snext = snxt;
} template<typename T> //辅助队列,删除结点 Quefd:queue for delete
struct Quefd //此队列同时在后根遍历中做临时堆栈
{
T ddata;
Quefd<T>* dnext;
Quefd(const T& ddt, Quefd<T>* dnxt);
}; template<typename T> //Quefd构造函数
Quefd<T>::Quefd(const T& ddt, Quefd<T>* dnxt)
{
ddata = ddt;
dnext = dnxt;
} template<typename T> //树类
class Tree
{
private:
Node<T>* root;
Quefh<T> *hhead, *htail;
Quefs<T> *shead, *stail;
Quefd<T> *dhead, *dtail,*top;
int size;
int hsize;
int ssize;
int dsize;
public:
Tree();
~Tree();
void Operate();
private:
Node<T>* Creat(Node<T>* &rt);
void Destory(Node <T>* t);
void Addqh(Node<T>* pn, int levl);
void Addqs(Node<T>* spn);
void Addqd(const T& dedata);
void Outqh(Node<T>* &pn, int &levl);
Node<T>* Outqs();
void Delqh();
void Delqs();
void Delqd();
int Couhg(Node<T>* t);
Node<T>* GetFather(Node<T>* t, Node<T>* p);
void Search(Node<T>* t, const T& item, bool& sign);
void Del(Node<T>* t);
void D_ShowAll(Quefd<T>* dheader);
void FiRoTra(Node<T>* rt, int& ct);
void MiRoTra(Node<T>* rt, int& ct);
void LeveTra(Node<T>* t);
void ShowAll(Quefs<T>* header);
Node<T>* Push(Node<T>* t);
void PopAll(int& ct);
}; template<typename T> //类构造函数
Tree<T>::Tree()
{
root = NULL;
hhead = NULL;
htail = NULL;
shead = NULL;
stail = NULL;
dhead = NULL;
dtail = NULL;
top = NULL;
size = ;
hsize = ;
ssize = ;
dsize = ;
} template<typename T> //类析构函数
Tree<T>::~Tree()
{
Destory(root);
} template<typename T> //Quefh入队一个结点
void Tree<T>::Addqh(Node<T>* pn, int levl)
{
if (!hhead){ hhead = htail = new Quefh<T>(pn, levl, NULL); hsize = ; }
else
{
htail->hnext = new Quefh<T>(pn, levl, NULL);
htail = htail->hnext;
hsize++;
}
} template<typename T> //Quefh出队一个结点
void Tree<T>::Outqh(Node<T>* &pn, int &levl)
{
pn = hhead->nodrs;
levl = hhead->leve;
Quefh<T>* itemph;
itemph = hhead;
hhead = hhead->hnext;
delete itemph;
hsize--;
} template<typename T> //清空队列Quefh
void Tree<T>::Delqh()
{
while (hhead)
{
Quefh<T>* itemphd;
itemphd = hhead; hhead = hhead->hnext; delete itemphd;
}
} template<typename T> //Quefs入队一个结点
void Tree<T>::Addqs(Node<T>* spn)
{
if (!shead){ shead = stail = new Quefs<T>(spn, NULL); ssize = ; }
else
{
stail->snext = new Quefs<T>(spn, NULL);
stail = stail->snext;
ssize++;
}
} template<typename T> //Quefs出队一个结点
Node<T>* Tree<T>::Outqs()
{
Node<T>* pn;
pn = shead->snodrs;
Quefs<T>* itemps;
itemps = shead;
shead = shead->snext;
delete itemps;
ssize--;
return pn;
} template<typename T> //输出队列Quefs内全部元素
void Tree<T>::ShowAll(Quefs<T>* header)
{
Quefs<T>* p = header;
for (int i = ; i <= ssize; i++)
{
cout << p->snodrs << " ";
if (i % == )cout << endl;
p = p->snext;
}
cout << endl;
} template<typename T> //清空队列Quefs
void Tree<T>::Delqs()
{
Quefs<T>* itempsd;
while(shead){ itempsd = shead; shead = shead->snext; delete itempsd; }
} template<typename T> //Quefd入队一个结点
void Tree<T>::Addqd(const T& dedata)
{
if (!dhead){ dhead = dtail = new Quefd<T>(dedata, NULL); dsize = ; }
else
{
dtail->dnext = new Quefd<T>(dedata, NULL);
dtail = dtail->dnext;
dsize++;
}
} template<typename T> //输出队列Quefd内全部元素
void Tree<T>::D_ShowAll(Quefd<T>* dheader)
{
Quefd<T>* dp = dheader;
for (int i = ; i <= dsize; i++)
{
cout << setiosflags(ios::left);
cout << setw() << dp->ddata;
if (i % == )cout << endl;
dp = dp->dnext;
}
cout << endl;
} template<typename T> //利用结构体Quefd构造的临时堆栈的入队操作
Node<T>* Tree<T>::Push(Node<T>* t)
{
while (!t->right)
{
top = new Quefd<T>(t->data, top);
t = t->left;
}
return t;
} template<typename T> //一次性弹出队列中所有元素
void Tree<T>::PopAll(int& ct)
{
while (top)
{
cout << setiosflags(ios::left);
cout << setw() << top->ddata;
ct++;
if (ct % == )cout << endl;
Quefd<T>* itemp4;
itemp4 = top; top = top->dnext; delete itemp4;
}
}
template<typename T> //清空队列Quefs
void Tree<T>::Delqd()
{
Quefd<T>* itempdd;
while (dhead){ itempdd = dhead; dhead = dhead->dnext; delete itempdd; }
} template<typename T> //创建树
Node<T>* Tree<T>::Creat(Node<T>* &rt)
{
int choice; bool flag;
if (size > )
{
cout << "是否继续创建子树?是请按1,否请按0:" << endl;
cin >> choice;
flag = true;
}
if (size == )
{
cout << "请输入根结点数据;" << endl;
T data; cin >> data;
rt = new Node<T>(data);
if (!rt){ cout << "根结点创建失败!" << endl; return NULL; }
size++;
flag = false;
cout << "根结点创建成功!" << endl;
cout << "目前树中共有结点" << size << "个。" << endl;
}
if (flag)
{
if (choice == )return ;
else
{
cout << "请输入子结点数据;" << endl;
T data; cin >> data;
rt = new Node<T>(data);
if (!rt){ cout << "子结点创建失败!" << endl; return NULL; }
size++;
cout << "子结点创建成功!" << endl;
cout << "目前树中共有结点" << size << "个。" << endl;
}
}
Creat(rt->left);
Creat(rt->right);
return root;
} template<typename T> //先根递归遍历 FiRoTra是first root traversal的缩写
void Tree<T>::FiRoTra(Node<T>* rt, int& ct)
{
if (rt)
{
cout << setiosflags(ios::left);
cout << setw() << rt->data;
ct++;
if (ct % == )
cout << endl;
FiRoTra(rt->left, ct);
FiRoTra(rt->right, ct);
}
} template<typename T> //中根递归遍历 MiRoTra是middle root traversal的缩写 这里用来进行树的后根遍历
void Tree<T>::MiRoTra(Node<T>* rt, int& ct)
{
if (rt)
{
MiRoTra(rt->left, ct);
cout << setiosflags(ios::left);
cout << setw() << rt->data;
ct++;
if (ct % == )
cout << endl;
MiRoTra(rt->right, ct);
}
} template<typename T> //层次遍历 LeveTra是level traversal的缩写
void Tree<T>::LeveTra(Node<T>* t)
{
int count=;
Node<T>* pt;
Addqs(t);
while (ssize>)
{
pt = Outqs();
count++;
cout << setiosflags(ios::left);
cout << setw() << pt->data;
if (count % == )cout << endl;
pt = pt->left;
while (pt)
{
Addqs(pt);
pt = pt->right;
}
}
}
template<typename T> //计算树高
int Tree<T>::Couhg(Node<T>* t)
{
int level = , lev, max = ;
Node<T>* pt;
Addqh(t, level);
while (hsize>)
{
Outqh(pt, lev);
level = lev + ;
if (max < lev)max = lev;
while (pt)
{
if (pt->left)Addqh(pt->left, level);
pt = pt->right;
}
}
hhead = htail = NULL;
return max;
} template<typename T> //搜索数据域为某值的结点
void Tree<T>::Search(Node<T>* t, const T& item, bool& sign)
{
if (t)
{
Search(t->left, item, sign);
Search(t->right, item, sign);
if (t->data == item){ sign = true; Addqs(t); }
}
} template<typename T> //得到某结点(以地址为关键值)的父结点的地址
Node<T>* Tree<T>::GetFather(Node<T>* t, Node<T>* p)
{
Node<T>* q;
if (t == NULL)return NULL;
if (t->left == p || t->right == p)return t;
q = GetFather(t->left, p);
if (q != NULL)return q;
else return GetFather(t->right, p);
} template<typename T> //在树中删除以某结点为根的树
void Tree<T>::Del(Node<T>* t)
{
if (t != NULL)
{
Del(t->left);
Del(t->right);
Addqd(t->data);
delete t;
size--;
}
} template<typename T> //销毁树
void Tree<T>::Destory(Node<T>* t)
{
if (t != NULL)
{
Destory(t->left);
Destory(t->right);
delete t;
size--;
}
} template <typename T>
void Tree<T>::Operate()
{
bool flager = true;
while (flager)
{
cout << "请您选择操作(输入操作前的数字进行选择):" << endl;
cout << "1.创建树并写入数据" << endl;
cout << "2.先根遍历树" << endl;
cout << "3.计算树高" << endl;
cout << "4.后根遍历树" << endl;
cout << "5.层次遍历树" << endl;
cout << "6.搜索数据域为某值的结点" << endl;
cout << "7.删除数据域为某值的结点及其子树" << endl;
cout << "8.销毁树" << endl;
int choice;
cin >> choice;
switch (choice)
{
//由用户创建树
case :
{
if (root){ cout << "树已经创建,无需再建!若想新建,请您先销毁旧树!" << endl; break; }
Creat(root);
cout << "树创建完成!" << endl;
cout << "此树中共有结点" << size << "个!" << endl;
break;
}
//先根遍历树
case :
{
if (!root){ cout << "树还未创建或已被销毁,无法执行遍历操作,请您先创建树!" << endl; break; }
int counter2 = ;
FiRoTra(root, counter2);
cout << endl;
break;
}
//计算树高
case :
{
if (!root){ cout << "树还未创建或已被销毁,无法计算树高,请您先创建树!" << endl; break; }
int high;
high= Couhg(root);
cout << "树的高度为:" <<high<< endl;
break;
}
//后根遍历树
case :
{
if (!root){ cout << "树还未创建或已被销毁,无法执行遍历操作,请您先创建树!" << endl; break; }
Node<T>* pt4 = Push(root);
int counter4 = ;
MiRoTra(pt4, counter4);
PopAll(counter4);
cout << endl;
break;
}
//层次遍历树
case :
{
if (!root){ cout << "树还未创建或已被销毁,无法执行遍历操作,请您先创建树!" << endl; break; }
LeveTra(root);
cout << endl;
shead = stail = NULL;
break;
}
//搜索数据域为某值的结点
case :
{
if (!root){ cout << "树还未创建或已被销毁,无法执行搜索操作,请您先创建树!" << endl; break; }
cout << "请您输入数据域的值;" << endl;
T indata; cin >> indata;
bool flag = false;
Search(root, indata, flag);
if (!flag){ cout << "该树中没有数据域为" << indata << "的结点!" << endl; break; }
else cout << "该树中数据域为" << indata << "的结点共有" << ssize << "个。" << endl;
cout << "是否输出这些结点的地址?是请按1,否则按0:" << endl;
int choice6; cin >> choice6;
if (choice6 == ) ShowAll(shead);
Delqs(); shead = stail = NULL; ssize = ;
break;
}
//删除数据域为某值的结点及其子树
case :
{
if (!root){ cout << "树还未创建或已被销毁,无法执行删除操作,请您先创建树!" << endl; break; }
T data7; bool flag7 = false; bool sign7 = true; int choice7;
cout << "请您输入结点数据的值:" << endl;
cin >> data7;
Search(root, data7, flag7);
if (!flag7){ cout << "目前树中无数据域为" << data7 << "的结点!" << endl; break; }
while (sign7)
{
Node<T> *p7, *fp7;
Quefs<T> *item7;
p7 = shead->snodrs;
item7 = shead; shead = shead->snext; delete item7; ssize--;
if (p7 == root)
{
cout << "数据域为" << data7 << "的结点为根结点,若执行删除操作将会销毁整棵树!" << endl;
cout << "是否确定执行删除操作?确定请按1,取消请按0:" << endl;
cin >> choice7;
if (choice7 == ){ Delqs(); shead = stail = NULL; ssize = ; goto mark7; }
else
{
Destory(p7); root = NULL; size = ;
cout << "删除成功!同时整棵树也被销毁!" << endl;
Delqs(); shead = stail = NULL; ssize = ;
goto mark7;
}
}
fp7 = GetFather(root, p7);
if (p7->right) //其实这两个if可以合成一个,但考虑到程序的可读性,分开来写
{
if (fp7->left == p7)fp7->left = p7->right;
if (fp7->right == p7) fp7->right = p7->right;
p7->right = NULL;
}
if (!p7->right)
{
if (fp7->left == p7)fp7->left = NULL;
if (fp7->right == p7)fp7->right = NULL;
}
Del(p7);
cout << "删除成功!" << endl;
if (ssize == ){ cout << "此时树中已无数据域为" << data7 << "的结点及其子树!" << endl; sign7 = false; }
if (ssize > ){ cout << "但此时树中数据域为" << data7 << "的结点还有" << ssize << "个!" << endl; }
cout << "此次共删除结点" << dsize << "个," << "目前树中还有结点" << size << "个。" << endl;
cout << "是否显示被删除的各结点的值?是请按1,否则请按0:" << endl;
cin >> choice7;
if (choice7 == )D_ShowAll(dhead);
Delqd(); dhead = dtail = NULL; dsize = ;
if (ssize > )
{
cout << "是否继续删除数据域为" << data7 << "的结点及其子树?是请按1,否则按0:" << endl;
cin >> choice7;
if (choice7 == )sign7 = false;
}
}
Delqs(); shead = stail = NULL; ssize = ;
mark7:break;
} //销毁树
case :
{
if (!root){ cout << "树还未创建或已被销毁!" << endl; break; }
cout << "您确定销毁该树吗?确定请按1,取消请按0:" << endl;
int choice8; cin >> choice8;
if (choice8 == )break;
else Destory(root);
root = NULL;
size = ;
cout << "树已销毁!" << endl;
break;
}
//处理用户的错误输入
default:
{
cout << "您的输入有误,无法进行操作!" << endl;
break;
} }//switch结束
//控制循环
cout << "是否继续?继续请按1,退出请按0:" << endl;
int ifgoon;
cin >> ifgoon;
if (ifgoon == )flager = false;
}//while结束
} #endif //.cpp文件 #include"Tree.h"
#include<iostream>
using namespace std;
int main()
{
//是否进入程序
int uscho; bool flag = true;//uscho:user choice的缩写
cout << "敬告;请您务必按提示要求操作,如果您进行了规定以外的操作,由此造成的一切后果,将全部由您个人承担,程序开发者概不负责!" << endl;
cout << "是否进入程序?进入请按1,否则按0;" << endl;
cin >> uscho;
if (uscho == ) return ;
//用户选择类型
while (flag)
{
cout << "请选择您所要创建树的数据类型,输入类型前的数字进行选择;" << endl;
cout << "1.整型 2.浮点 3.字符" << endl;
cin >> uscho;
if (uscho != && uscho != && uscho != )
{
cout << "您的输入有误!重新输入请按1,退出请按0:" << endl;
cin >> uscho;
if (uscho == )return ;
else flag = false;
}
if (flag) flag = false;
else flag = true;
}
switch (uscho)
{
case :
{
Tree<int> tree_int;
tree_int.Operate();
break;
}
case :
{
Tree<float> tree_float;
tree_float.Operate();
break;
}
case :
{
Tree<char> tree_char;
tree_char.Operate();
break;
}
default:
cout << "您的输入有误!" << endl;
break;
}
return ;
} Ⅳ.结语: 代码已经过测试,在VS2013上成功运行!
发此文有两大目的:
.和大家交流经验,供需要的人参考。
.在下菜鸟,代码中难免有不妥之处,恳求大神批评指正。您的批评就是在下提高的起点,对于您的
批评,在下将不胜感激!
C++实现树的基本操作,界面友好,操作方便,运行流畅,运用模板的更多相关文章
- C++实现二叉树,运用模板,界面友好,操作方便 运行流畅
//.h文件 #ifndef TREE_H #define TREE_H #include<iostream> #include<iomanip> using namespac ...
- 伸展树的基本操作——以【NOI2004】郁闷的出纳员为例
前两天老师讲了伸展树……虽然一个月以前自己就一直在看平衡树这一部分的书籍,也仔细地研读过伸展树地操作代码,但是就是没写过程序……(大概也是在平衡树的复杂操作和长代码面前望而生畏了)但是今天借着老师布置 ...
- linux复习3:linux字符界面的操作
一.前言 1.对linux服务器进行管理的时候,经常要进入字符界面进行操作,使用命令需要记住该命令的相关选项和参数.vi编辑器可以用于编辑任何ASCII文本,功能非常的强大,可以对文本进行创建.查找. ...
- Avl树的基本操作(c语言实现)
#include<stdio.h> #include<stdlib.h> typedef struct AvlNode *Position; typedef struct Av ...
- 同花顺核新下单程序的"界面不操作超时时间"的设定
"界面不操作超时时间"的设定 同花顺核新下单程序的'界面不操作超时时间'的设定 系统> 系统设置> 界面设置> 界面不操作超时时间(分): 在这个输入框里填上个3 ...
- python文件(概念、基本操作、常用操作、文本文件的编码方式)
文件 目标 文件的概念 文件的基本操作 文件/文件夹的常用操作 文本文件的编码方式 01. 文件的概念 1.1 文件的概念和作用 计算机的 文件,就是存储在某种 长期储存设备 上的一段 数据 长期存储 ...
- Rattle:数据挖掘的界面化操作
R语言是一个自由.免费.源代码开放的软件,它是一个用于统计计算和统计制图的优秀工具.这里的统计计算可以是数据分析.建模或是数据挖掘等,通过无数大牛提供的软件包,可以帮我们轻松实现算法的实施. 一些读者 ...
- MongoDB的安装配置、基本操作及Perl操作MongoDB
MongoDB的安装配置.基本操作及Perl操作MongoDB http://www.myhack58.com/Article/60/63/2014/42353.htm
- python学习9—文件基本操作与高级操作
python学习9—文件基本操作与高级操作 1. 文件基本操作 打开文件,获得文件句柄:f = open('filename',encoding='utf-8'),open会查询操作系统的编码方式,并 ...
- 使用Python爬虫库BeautifulSoup遍历文档树并对标签进行操作详解(新手必学)
为大家介绍下Python爬虫库BeautifulSoup遍历文档树并对标签进行操作的详细方法与函数下面就是使用Python爬虫库BeautifulSoup对文档树进行遍历并对标签进行操作的实例,都是最 ...
随机推荐
- 修改RectTransform的宽度和高度
rectTransform.sizeDelta = new Vector2( width, height);
- BizTalk开发系列(七) Hello World2
之前根据BizTalk的订阅原理,使用BizTalk管理控制台创建了第一个应用程序 Hello World.但是由于控制台的开发功能有限,绝大多数的BizTalk程序都是在集成开发环境Visual S ...
- poj3292-Semi-prime H-numbers(筛法打表)
一,题意: 一个H-number是所有的模四余一的数.(x=4*k+1) 如果一个H-number是H-primes 当且仅当它的因数只有1和它本身(除1外). 一个H-number是H-semi ...
- String-原型属性(练习)
1.js部分/* *字符串新功能,添加一个字符串转成数组. *返回一个数组 */String.prototype.toCharArray = function(){ //定义一个数组 var chs ...
- MySQL Access denied for user root@localhost 解决方法
今天把本地开发的项目(ThinkPHP 3.2.3)移到虚拟机上(CentOS 6.6,LNMP 1.2,MySQL 5.6.23),配置好 MySQL 之后访问首页,出现: 此时 MySQL 的用户 ...
- JBoss和Tomcat版本、及Servlet、JSP规范版本对应一览 【转】
原文地址:http://blog.csdn.net/hills/article/details/40896357 JBoss和Tomcat版本.及Servlet.JSP规范版本对应一览 JBossAS ...
- Nest查询示例
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- 《Linux内核分析》第七周 读书笔记
<深入理解计算机系统>CHAPTER7阅读梳理 [学习时间:3hours] [学习内容:链接需要的代码&数据:链接机制:链接生成的目标文件] 一.链接概述 1.链接 定义:链接是将 ...
- 【C语言学习笔记】存储类、链接和内存管理
因为对内存管理部分一直没有很清楚的思路,所以一直在找资料想系统看一下这部分的内容.在C primer plus里看到了这一章,虽然大多都是心知肚明的东西,但是还是很多概念性系统性的东西让我眼前一亮,把 ...
- tesseract ocr文字识别Android实例程序和训练工具全部源代码
tesseract ocr是一个开源的文字识别引擎,Android系统中也可以使用.可以识别50多种语言,通过自己训练识别库的方式,可以大大提高识别的准确率. 为了节省大家的学习时间,现将自己近期的学 ...