Ⅰ.说明:

    .采用左孩子右兄弟的方式,转化为二叉树来实现。

    .树的后根遍历与二叉树的中根遍历即有联系又有区别,请读者注意分析体会。

Ⅱ.功能:

    .创建树并写入数据

    .先根遍历树

    .计算树高

    .后根遍历树

    .层次遍历树

    .搜索数据域为某值的结点

    .删除数据域为某值的结点及其子树

    .销毁树

Ⅲ.代码:

//.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++实现树的基本操作,界面友好,操作方便,运行流畅,运用模板的更多相关文章

  1. C++实现二叉树,运用模板,界面友好,操作方便 运行流畅

    //.h文件 #ifndef TREE_H #define TREE_H #include<iostream> #include<iomanip> using namespac ...

  2. 伸展树的基本操作——以【NOI2004】郁闷的出纳员为例

    前两天老师讲了伸展树……虽然一个月以前自己就一直在看平衡树这一部分的书籍,也仔细地研读过伸展树地操作代码,但是就是没写过程序……(大概也是在平衡树的复杂操作和长代码面前望而生畏了)但是今天借着老师布置 ...

  3. linux复习3:linux字符界面的操作

    一.前言 1.对linux服务器进行管理的时候,经常要进入字符界面进行操作,使用命令需要记住该命令的相关选项和参数.vi编辑器可以用于编辑任何ASCII文本,功能非常的强大,可以对文本进行创建.查找. ...

  4. Avl树的基本操作(c语言实现)

    #include<stdio.h> #include<stdlib.h> typedef struct AvlNode *Position; typedef struct Av ...

  5. 同花顺核新下单程序的"界面不操作超时时间"的设定

    "界面不操作超时时间"的设定 同花顺核新下单程序的'界面不操作超时时间'的设定 系统> 系统设置> 界面设置> 界面不操作超时时间(分): 在这个输入框里填上个3 ...

  6. python文件(概念、基本操作、常用操作、文本文件的编码方式)

    文件 目标 文件的概念 文件的基本操作 文件/文件夹的常用操作 文本文件的编码方式 01. 文件的概念 1.1 文件的概念和作用 计算机的 文件,就是存储在某种 长期储存设备 上的一段 数据 长期存储 ...

  7. Rattle:数据挖掘的界面化操作

    R语言是一个自由.免费.源代码开放的软件,它是一个用于统计计算和统计制图的优秀工具.这里的统计计算可以是数据分析.建模或是数据挖掘等,通过无数大牛提供的软件包,可以帮我们轻松实现算法的实施. 一些读者 ...

  8. MongoDB的安装配置、基本操作及Perl操作MongoDB

    MongoDB的安装配置.基本操作及Perl操作MongoDB http://www.myhack58.com/Article/60/63/2014/42353.htm

  9. python学习9—文件基本操作与高级操作

    python学习9—文件基本操作与高级操作 1. 文件基本操作 打开文件,获得文件句柄:f = open('filename',encoding='utf-8'),open会查询操作系统的编码方式,并 ...

  10. 使用Python爬虫库BeautifulSoup遍历文档树并对标签进行操作详解(新手必学)

    为大家介绍下Python爬虫库BeautifulSoup遍历文档树并对标签进行操作的详细方法与函数下面就是使用Python爬虫库BeautifulSoup对文档树进行遍历并对标签进行操作的实例,都是最 ...

随机推荐

  1. JS写的CRC16校验算法(查表法)

    var CRC = {}; CRC._auchCRCHi = [ 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0 ...

  2. centos yum 使用笔记

    yum 参数说明yum -y # 表示自动选择 基本使用# yum -y install 包名(支持*) :自动选择y,全自动# yum install 包名(支持*) :手动选择y or n# yu ...

  3. 20145221高其&20145326蔡馨熠《信息安全系统设计基础》实验二 固件设计

    20145221高其&20145326蔡馨熠<信息安全系统设计基础>实验二 固件设计 实验目的与要求 了解多线程程序设计的基本原理,学习 pthread 库函数的使用. 了解在 l ...

  4. WPF 关于窗口的一些显示效果

    0. 一些常用尺寸大小: 1920x1080; 1600x900; 1280x720; 1024x576; 1. 设置窗口的边框样式 使用 Window.WindowStyle 属性可以设置窗口的边框 ...

  5. UIView添加手势

    _shareImage.userInteractionEnabled=YES; UITapGestureRecognizer *imagegesture=[[UITapGestureRecognize ...

  6. How to prevent SQL injection attacks?

    In our earlier tutorial on SQL Injection, one way to have prevented the SQL injection attack was by ...

  7. 制作U盘启动盘及安装操作系统的方法

    U盘启动盘制作方法: 1.从网上下载最新的老毛桃U盘启动制作工具主程序并安装 2.插入U盘(制作启动盘前先保存好你的资料到其它地方,以防丢失不可找回) 3.插入正确的U盘后程序会自动检测到U盘,启动模 ...

  8. 使用Xcode6和IOS8SDK以后遇到的问题

    定位.苹果在IOS8里面修改了定位授权协议,也就意味着你原来的app在ios8上很可能无法定位.目前最好的办法就是在app启动的时候调用IOS8的定位授权API来获取用户的授权,这样就不要在其他地方做 ...

  9. 用命令实现SQLServerr的备份与还原

    一.备份数据库,命令如下: USE master; GO BACKUP DATABASE mytest TO DISK='E:\disk\mytest.bak' /* mytest为数据库名称,'E: ...

  10. AngularJS Best Practices: ngRoute

    app/----- components/---------- users/--------------- controllers/-------------------- users.control ...