//.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> //队列结点
struct QNode
{
Node<T>* pdata;
QNode<T>* next;
QNode( Node<T>* &pd, QNode* tp);
}; template<typename T> //队列结点初始化
QNode<T>::QNode( Node<T>* &pd, QNode* tp)
{
pdata = pd;
next = tp;
} template<typename T> //放删除元素的队列结点
struct DQNode
{
T d_data;
DQNode<T>* dnext;
DQNode(const T& ditem, DQNode<T>* dp);
}; template<typename T> //放删除元素的队列结点初始化
DQNode<T>::DQNode(const T& ditem, DQNode<T>* dp)
{
d_data = ditem;
dnext = dp;
} template<typename T> //二叉树类
class Tree
{
private:
Node<T>* root;
QNode<T>* head, *tail;
DQNode<T>*dhead, *dtail;
int size;//记录二叉树结点长度
int qsize;//记录队列长度
int dsize;//记录DQNode队列长度
public:
Tree();
~Tree();
void Operate();
private:
Node<T>* Creat(Node<T>* &rt);
void Destory(Node<T>* t);
void Del(Node<T>* t);
void FiRoTra(Node<T>* rt ,int& ct);
void MiRoTra(Node<T>* rt, int& ct);
void LaRoTra(Node<T>* rt, int& ct);
void LeveTra(Node<T>* rt, int& ct);
void Addq( Node<T>* &pt);
Node<T>* Outq();
void AddDq(const T& tdata);
void Delq();
void Deld();
void ShowAll(QNode<T>* header);
void D_ShowAll(DQNode<T>* dheader);
Node<T>* GetFather(Node<T>* t, Node<T>* p);
void Search(Node<T>* t, const T& item, bool& sign);
}; template<typename T> //类构造函数
Tree<T>::Tree()
{
root = NULL;
head = NULL;
tail = NULL;
dhead = NULL;
dtail = NULL;
size = ;
qsize = ;
dsize = ;
} template<typename T> //类析构函数
Tree<T>::~Tree()
{
Destory(root);
} template<typename T> //入队一个元素
void Tree<T>::Addq( Node<T>* &pnode)
{
if (!head){ head = tail = new QNode<T>(pnode,NULL); qsize = ; }
else
{
tail->next = new QNode<T>(pnode, NULL);
tail = tail->next;
qsize++;
}
} template<typename T> //出队一个元素
Node<T>* Tree<T>::Outq()
{
Node<T>* p;
QNode<T>* item;
p = head->pdata;
item = head;
head = head->next;
delete item;
qsize--;
return p;
} template<typename T> //DQNode入队一个元素
void Tree<T>:: AddDq(const T& tdata)
{
if (!dhead){ dhead = dtail = new DQNode<T>(tdata, NULL); dsize = ; }
else
{
dtail->dnext = new DQNode<T>(tdata, NULL);
dtail = dtail->dnext;
dsize++;
}
} template<typename T> //清空队列
void Tree<T>::Delq()
{
while (head)
{
QNode<T>* temp;
temp = head; head = head->next; delete temp;
}
} template<typename T> //清空DQNode队列
void Tree<T>::Deld()
{
while (dhead)
{
DQNode<T>* dtemp;
dtemp = dhead; dhead = dhead->dnext; delete dtemp;
}
} template<typename T> //输出队列内全部元素
void Tree<T>::ShowAll(QNode<T>* header)
{
QNode<T>* p = header;
for (int i = ; i <= qsize;i++)
{
cout << p->pdata << " ";
if (i % == )cout << endl;
p = p->next;
}
cout << endl;
} template<typename T> //输出DQNode队列内全部元素
void Tree<T>::D_ShowAll(DQNode<T>* dheader)
{
DQNode<T>* dp = dheader;
for (int i = ; i <= dsize; i++)
{
cout << setiosflags(ios::left);
cout<<setw() << dp->d_data;
if (i % == )cout << endl;
dp = dp->dnext;
}
cout << endl;
} 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);
AddDq(t->data);
delete t;
size--;
}
} 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> //后根递归遍历 LaRoTra是last root traversal的缩写
void Tree<T>::LaRoTra(Node<T>* rt, int& ct)
{
if (rt)
{
LaRoTra(rt->left, ct);
LaRoTra(rt->right, ct);
cout << setiosflags(ios::left);
cout<<setw() << rt->data ;
ct++;
if (ct % == )
cout << endl;
}
} template<typename T> //层次遍历 LeveTra是level traversal的缩写
void Tree<T>::LeveTra(Node<T>* rt, int& ct)
{
Addq(rt);
Node<T>* lt;
while (qsize>)
{
lt=Outq();
ct++;
cout << setiosflags(ios::left);
cout <<setw()<< lt->data ;
if (ct % == )
cout << endl;
if (lt->left != NULL)Addq(lt->left);
if (lt->right != NULL)Addq(lt->right);
}
} 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; Addq(t);}
}
} 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;
cout << "9.销毁二叉树" << 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 counter3 = ;
MiRoTra(root, counter3);
cout << endl;
break;
}
//后根遍历二叉树
case :
{
if (!root){ cout << "二叉树还未创建或已被销毁,无法执行遍历操作,请您先创建二叉树!" << endl; break; }
int counter4 = ;
LaRoTra(root, counter4);
cout << endl;
break;
}
//层次遍历二叉树
case :
{
if (!root){ cout << "二叉树还未创建或已被销毁,无法执行遍历操作,请您先创建二叉树!" << endl; break; }
int counter5 = ;
LeveTra(root, counter5);
cout << endl;
head = tail = 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 << "的结点共有"<<qsize<<"个。" << endl;
cout << "是否输出这些结点的地址?是请按1,否则按0:" << endl;
int choice6; cin >> choice6;
if (choice6 == ) ShowAll(head);
Delq(); head = tail = NULL; qsize = ;
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; Delq(); head = tail = NULL; qsize = ; break; }
while (sign7)
{
Node<T> *p7, *fp7;
QNode<T> *item7;
p7 = head->pdata;
item7 = head; head = head->next; delete item7; qsize--;
if (p7 == root)
{
cout << "数据域为"<<data7<<"的结点为根结点,若执行删除操作将会销毁整棵二叉树!" << endl;
cout << "是否确定执行删除操作?确定请按1,取消请按0:" << endl;
cin >> choice7;
if (choice7 == ){ Delq(); head = tail = NULL; qsize = ; goto mark7; }
else
{
Destory(p7); root = NULL; size = ;
root = NULL;
cout << "删除成功!同时整棵二叉树也被销毁!" << endl;
Delq(); head = tail = NULL; qsize = ;
goto mark7;
}
}
fp7 = GetFather(root, p7);
if (fp7->left == p7)fp7->left = NULL;
else fp7->right = NULL;
Del(p7);
cout << "删除成功!" << endl;
if (qsize == ){ cout << "此时树中已无数据域为" << data7 << "的结点及其子树!" << endl; sign7 = false; }
if (qsize > ){ cout << "但此时树中数据域为" << data7 << "的结点还有" <<qsize<<"个!"<< endl; }
cout << "此次共删除结点" << dsize << "个," << "目前树中还有结点" << size << "个。" << endl;
cout << "是否显示被删除的各结点的值?是请按1,否则请按0:" << endl;
cin >> choice7;
if (choice7 == )D_ShowAll(dhead);
Deld(); dhead = dtail = NULL; dsize = ;
if (qsize > )
{
cout << "是否继续删除数据域为" <<data7<<"的结点及其子树?是请按1,否则按0:"<< endl;
cin >> choice7;
if (choice7 == )sign7 = false;
}
}
Delq(); head = tail = NULL; qsize = ;
mark7:break;
}
//判断是否为完全二叉树
case :
{
if (!root){ cout << "二叉树还未创建或已被销毁,无法进行判断,请您先创建二叉树!" << endl; break; }
bool branch=false;
Addq(root);
while (qsize>)
{
Node<T>* pt;
pt = Outq();
if (!branch)
{
if (pt->left == NULL&&pt->right != NULL)
{
cout << "目前的二叉树不是完全二叉树!" << endl;
Delq(); head = tail = NULL; qsize = ;
goto mark8;
}
if (pt->right==NULL)
{
branch = true;
}
}
else
{
if (pt->left != NULL || pt->right != NULL)
{
cout << "目前的二叉树不是完全二叉树!" << endl;
Delq(); head = tail = NULL; qsize = ;
goto mark8;
}
}
if (pt->left != NULL)Addq(pt->left);
if (pt->right != NULL)Addq(pt->right);
}
cout << "目前的二叉树是完全二叉树!" << endl;
head = tail = NULL;
mark8:break;
}
//销毁二叉树
case :
{
if (!root){ cout << "二叉树还未创建或已被销毁!" << endl; break; }
cout << "您确定销毁该二叉树吗?确定请按1,取消请按0:" << endl;
int choice9; cin >> choice9;
if (choice9 == )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. 同花顺核新下单程序的"界面不操作超时时间"的设定

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

  2. python第一百零五天 ---Django 基础 路由系统 URL 模板语言 ORM 操作

    一 路由系统 URL 1 url(r'^index/',views.index) url(r'^home/', views.Home.as_view()) 2 url(r'^detail-(\d+). ...

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

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

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

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

  5. python框架Django中MTV框架之Template(模板/界面)

    MTV框架之Template(模板/界面) 关注公众号"轻松学编程"了解更多. 1.模板目录位置 应用下 不需要注册 无法跨应用地进行复用 工程下 需要注册 settings.py ...

  6. C++实现树的基本操作,界面友好,操作方便,运行流畅,运用模板

    Ⅰ.说明: .采用左孩子右兄弟的方式,转化为二叉树来实现. .树的后根遍历与二叉树的中根遍历即有联系又有区别,请读者注意分析体会. Ⅱ.功能: .创建树并写入数据 .先根遍历树 .计算树高 .后根遍历 ...

  7. C++实现链式栈,运用模板,界面友好,操作方便,运行流畅

    //.h文件 #ifndef STACK_H #define STACK_H #include<iostream> #include<iomanip> using namesp ...

  8. C++实现有向权图的基本操作,界面友好,操作方便,运行流畅

    Ⅰ.功能: .创建图 .展示全图 .添加顶点 .添加边 .删除顶点 .删除边 .查看指定边权值 .修改指定边权值 .输出两点间的所有简单路及路径对应权值 .销毁图 ps:关于9,如果不存在任何简单路, ...

  9. C++,利用链式栈实现括号匹配,界面友好,操作方便,运行流畅

    #include<iostream> #include<string> using namespace std; struct Node { char ch; Node* ne ...

随机推荐

  1. 【sinatra】安装测试

    $ gem install sinatra 测试: $ subl app.rb app.rb内容: require 'sinatra' get '/' do "Hello, World!&q ...

  2. linux计划任务运行php文件的方法

    在linux下,借助crontab,设置计划任务每天6点10分执行filename.php文件,写入一行时间到log日志中. 创建计划任务的脚本: dos2unix /path/to/filename ...

  3. 在路由器 RT-AC68U 安装迅雷远程过程

    赶紧记录下,省得时间久了忘记.  步骤如下: 1.下载迅雷远程的 Linux 组件: http://pan.baidu.com/s/1jGqYPnw . 解压缩. 2.ssh 登录au68u 路由器 ...

  4. php的ssh2扩展安装

    折腾半天,结论如下: 1.先需要openssl 用which openssl看是否已安装 2.然后libssh2 用rpm -ql libssh2查看 3.下载源码的shh2x.x.x.tgz的包 4 ...

  5. Java 基本数据类型 sizeof 功能【转】

    转自:http://blog.csdn.net/sunboy_2050/article/details/7310008 版权声明:本文为博主原创文章,未经博主允许不得转载. Java基本数据类型int ...

  6. android:layout_gravity和android:gravity属性的区别

    一.介绍: gravity的中文意思就是”重心“,就是表示view横向和纵向的停靠位置 (1).android:gravity:是对view控件本身来说的,是用来设置view本身的内容应该显示在vie ...

  7. js 如何生成唯一且不可预测的 ID

    通常数据库可以生成唯一的 ID,最多的就是数字序列,也有像 MongoDB 这样产生组合序列的,不过这种形式的 ID 由于是序列,是可以预测的.如果想得到不可预测且唯一的 ID,方法还是有的. 下面主 ...

  8. Recovery with Incremental Backups

    During media recovery, RMAN examines the restored files to determine whether it can recover them wit ...

  9. UINavigationController侧滑滑动返回 卡死问题

    UINavigationController滑动返回,有需要的朋友可以参考下. 最近做了UINavigationController的滑动返回(IOS7及以后系统默认支持的), 主要分成以下几步以及碰 ...

  10. 在JS函数中执行C#中的函数、字段

    1.调用字段 cs文件的代码: ; protected void Page_Load(object sender, EventArgs e) { id = ; } js页面的代码: function ...