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> //队列结点
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++实现二叉树,运用模板,界面友好,操作方便 运行流畅的更多相关文章
- 同花顺核新下单程序的"界面不操作超时时间"的设定
"界面不操作超时时间"的设定 同花顺核新下单程序的'界面不操作超时时间'的设定 系统> 系统设置> 界面设置> 界面不操作超时时间(分): 在这个输入框里填上个3 ...
- python第一百零五天 ---Django 基础 路由系统 URL 模板语言 ORM 操作
一 路由系统 URL 1 url(r'^index/',views.index) url(r'^home/', views.Home.as_view()) 2 url(r'^detail-(\d+). ...
- Rattle:数据挖掘的界面化操作
R语言是一个自由.免费.源代码开放的软件,它是一个用于统计计算和统计制图的优秀工具.这里的统计计算可以是数据分析.建模或是数据挖掘等,通过无数大牛提供的软件包,可以帮我们轻松实现算法的实施. 一些读者 ...
- linux复习3:linux字符界面的操作
一.前言 1.对linux服务器进行管理的时候,经常要进入字符界面进行操作,使用命令需要记住该命令的相关选项和参数.vi编辑器可以用于编辑任何ASCII文本,功能非常的强大,可以对文本进行创建.查找. ...
- python框架Django中MTV框架之Template(模板/界面)
MTV框架之Template(模板/界面) 关注公众号"轻松学编程"了解更多. 1.模板目录位置 应用下 不需要注册 无法跨应用地进行复用 工程下 需要注册 settings.py ...
- C++实现树的基本操作,界面友好,操作方便,运行流畅,运用模板
Ⅰ.说明: .采用左孩子右兄弟的方式,转化为二叉树来实现. .树的后根遍历与二叉树的中根遍历即有联系又有区别,请读者注意分析体会. Ⅱ.功能: .创建树并写入数据 .先根遍历树 .计算树高 .后根遍历 ...
- C++实现链式栈,运用模板,界面友好,操作方便,运行流畅
//.h文件 #ifndef STACK_H #define STACK_H #include<iostream> #include<iomanip> using namesp ...
- C++实现有向权图的基本操作,界面友好,操作方便,运行流畅
Ⅰ.功能: .创建图 .展示全图 .添加顶点 .添加边 .删除顶点 .删除边 .查看指定边权值 .修改指定边权值 .输出两点间的所有简单路及路径对应权值 .销毁图 ps:关于9,如果不存在任何简单路, ...
- C++,利用链式栈实现括号匹配,界面友好,操作方便,运行流畅
#include<iostream> #include<string> using namespace std; struct Node { char ch; Node* ne ...
随机推荐
- EBS常用小常识(转)
值集: 1.编辑信息:取上一个值集所选的数据.(值集关联) WHERE BANK_ACCOUNT_ID = :$FLEX$.CE_BANK_ACCOUNT_NUM_NAME ORDER BY STAT ...
- 【RoR win32】新建rails项目找不到script/server的解决办法
现象: D:\>rails new work/demo cd work/demo D:\work\demo>ruby script/server 这时显示出错: ruby: No such ...
- jquery冲突细节
使用jquery报一个错误,之前也遇到过,今天记录下来,方便以后使用 Uncaught TypeError: Object #<Object> has no method 'test' 这 ...
- 修改linux下mysql目录权限
1.进入当前目录:例cd /srun3/mysql 2.修改权用户限 chown -R mysql ipt_authd_remote(表示给ipt_authd_remotemysql权限) 3.修改用 ...
- Subversion简明手册--使用hook svn
使用 hook ,为了方便管理员 控制提交的过程 Subversion 提供了 hook 机制.当特定的 事件发生时,相应的 hook 会被调用, hook 其实就相当于特定 事件的处理函数.每个 h ...
- SQL Server 数据库中关于死锁的分析
SQL Server数据库发生死锁时不会像Oracle那样自动生成一个跟踪文件.有时可以在[管理]->[当前活动] 里看到阻塞信息(有时SQL Server企业管理器会因为锁太多而没有响应). ...
- 安装新版xampp后apache无法启动提示:Apache Service detected with wrong path解决方案
我以前安装过xampp,因为学习thingPHP需要升级PHP5.0以上,所以我就卸掉了xampp,从新安装新版本的xampp其中PHP是最新版的,但是安装后启动xampp提示如下:Apache Se ...
- phpize 动态添加 PHP 扩展的错误及解决方案
使用phpize 动态添加 PHP 扩展是开发中经常需要做的事情,但是在 macOS 中,首次使用该功能必然会碰到一些错误,本文列出了这些错误的解决方法. 问题一: 执行 phpize 报错如下: $ ...
- 输入框焦点时自动清除value
<!DOCTYPE html><html> <head> <meta charset="utf-8"> <script typ ...
- hihoCoder 搜索一·24点
题目1 : 搜索一·24点 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 周末,小Hi和小Ho都在家待着.在收拾完房间时,小Ho偶然发现了一副扑克,于是两人考虑用这副扑 ...