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

来源:互联网 发布:淘宝克隆别人店铺宝贝 编辑:程序博客网 时间:2024/05/16 13:57
复制代码
 Ⅰ.说明:    1.采用左孩子右兄弟的方式,转化为二叉树来实现。    2.树的后根遍历与二叉树的中根遍历即有联系又有区别,请读者注意分析体会。Ⅱ.功能:    1.创建树并写入数据    2.先根遍历树    3.计算树高    4.后根遍历树    5.层次遍历树    6.搜索数据域为某值的结点    7.删除数据域为某值的结点及其子树    8.销毁树Ⅲ.代码://.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 searchstruct 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 deletestruct 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 = 0;    hsize = 0;    ssize = 0;    dsize = 0;}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 = 1; }    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>           //清空队列Quefhvoid 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 = 1; }    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 = 1; i <= ssize; i++)    {        cout << p->snodrs << "  ";        if (i % 5 == 0)cout << endl;        p = p->snext;    }    cout << endl;}template<typename T>           //清空队列Quefsvoid 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 = 1; }    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 = 1; i <= dsize; i++)    {        cout << setiosflags(ios::left);        cout << setw(10) << dp->ddata;        if (i % 5 == 0)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(10) << top->ddata;        ct++;        if (ct % 5 == 0)cout << endl;        Quefd<T>* itemp4;        itemp4 = top; top = top->dnext; delete itemp4;    }}template<typename T>           //清空队列Quefsvoid 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 > 0)    {        cout << "是否继续创建子树?是请按1,否请按0:" << endl;        cin >> choice;        flag = true;    }    if (size == 0)    {        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 == 0)return 0;        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(10) << rt->data;        ct++;        if (ct % 5 == 0)            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(10) << rt->data;        ct++;        if (ct % 5 == 0)            cout << endl;        MiRoTra(rt->right, ct);    }}template<typename T>               //层次遍历 LeveTra是level traversal的缩写void Tree<T>::LeveTra(Node<T>* t){    int count=0;    Node<T>* pt;    Addqs(t);    while (ssize>0)    {        pt = Outqs();        count++;        cout << setiosflags(ios::left);        cout << setw(10) << pt->data;        if (count % 5 == 0)cout << endl;        pt = pt->left;        while (pt)        {            Addqs(pt);            pt = pt->right;        }    }}template<typename T>          //计算树高int Tree<T>::Couhg(Node<T>* t){    int level = 0, lev, max = 0;    Node<T>* pt;    Addqh(t, level);    while (hsize>0)    {        Outqh(pt, lev);        level = lev + 1;        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 1:        {                  if (root){ cout << "树已经创建,无需再建!若想新建,请您先销毁旧树!" << endl; break; }                  Creat(root);                  cout << "树创建完成!" << endl;                  cout << "此树中共有结点" << size << "个!" << endl;                  break;        }        //先根遍历树        case 2:        {                  if (!root){ cout << "树还未创建或已被销毁,无法执行遍历操作,请您先创建树!" << endl; break; }                  int counter2 = 0;                  FiRoTra(root, counter2);                  cout << endl;                  break;        }        //计算树高            case 3:        {                  if (!root){ cout << "树还未创建或已被销毁,无法计算树高,请您先创建树!" << endl; break; }                  int high;                  high= Couhg(root);                       cout << "树的高度为:" <<high<< endl;                  break;        }        //后根遍历树        case 4:        {                  if (!root){ cout << "树还未创建或已被销毁,无法执行遍历操作,请您先创建树!" << endl; break; }                  Node<T>* pt4 = Push(root);                  int counter4 = 0;                  MiRoTra(pt4, counter4);                  PopAll(counter4);                  cout << endl;                  break;        }        //层次遍历树        case 5:        {                  if (!root){ cout << "树还未创建或已被销毁,无法执行遍历操作,请您先创建树!" << endl; break; }                                LeveTra(root);                  cout << endl;                  shead = stail = NULL;                  break;        }        //搜索数据域为某值的结点            case 6:        {                  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 == 1)    ShowAll(shead);                  Delqs(); shead = stail = NULL; ssize = 0;                  break;        }        //删除数据域为某值的结点及其子树        case 7:        {                  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 == 0){ Delqs(); shead = stail = NULL; ssize = 0; goto mark7; }                          else                          {                              Destory(p7); root = NULL; size = 0;                              cout << "删除成功!同时整棵树也被销毁!" << endl;                              Delqs(); shead = stail = NULL; ssize = 0;                              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 == 0){ cout << "此时树中已无数据域为" << data7 << "的结点及其子树!" << endl; sign7 = false; }                      if (ssize > 0){ cout << "但此时树中数据域为" << data7 << "的结点还有" << ssize << "个!" << endl; }                      cout << "此次共删除结点" << dsize << "个," << "目前树中还有结点" << size << "个。" << endl;                      cout << "是否显示被删除的各结点的值?是请按1,否则请按0:" << endl;                      cin >> choice7;                      if (choice7 == 1)D_ShowAll(dhead);                      Delqd(); dhead = dtail = NULL; dsize = 0;                      if (ssize > 0)                      {                          cout << "是否继续删除数据域为" << data7 << "的结点及其子树?是请按1,否则按0:" << endl;                          cin >> choice7;                          if (choice7 == 0)sign7 = false;                      }                  }                  Delqs(); shead = stail = NULL; ssize = 0;              mark7:break;        }                //销毁树        case 8:        {                  if (!root){ cout << "树还未创建或已被销毁!" << endl; break; }                  cout << "您确定销毁该树吗?确定请按1,取消请按0:" << endl;                  int choice8; cin >> choice8;                  if (choice8 == 0)break;                  else Destory(root);                  root = NULL;                  size = 0;                  cout << "树已销毁!" << endl;                  break;        }            //处理用户的错误输入            default:        {                   cout << "您的输入有误,无法进行操作!" << endl;                   break;        }        }//switch结束        //控制循环        cout << "是否继续?继续请按1,退出请按0:" << endl;        int ifgoon;        cin >> ifgoon;        if (ifgoon == 0)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 == 0) return 0;    //用户选择类型    while (flag)    {        cout << "请选择您所要创建树的数据类型,输入类型前的数字进行选择;" << endl;        cout << "1.整型  2.浮点  3.字符" << endl;        cin >> uscho;        if (uscho != 1 && uscho != 2 && uscho != 3)        {            cout << "您的输入有误!重新输入请按1,退出请按0:" << endl;            cin >> uscho;            if (uscho == 0)return 0;            else  flag = false;        }        if (flag) flag = false;        else flag = true;    }    switch (uscho)    {    case 1:    {              Tree<int> tree_int;              tree_int.Operate();              break;    }    case 2:    {              Tree<float> tree_float;              tree_float.Operate();              break;    }    case 3:    {              Tree<char> tree_char;              tree_char.Operate();              break;    }    default:        cout << "您的输入有误!" << endl;        break;    }    return 0;}Ⅳ.结语:    代码已经过测试,在VS2013上成功运行!    发此文有两大目的:    1.和大家交流经验,供需要的人参考。    2.在下菜鸟,代码中难免有不妥之处,恳求大神批评指正。您的批评就是在下提高的起点,对于您的      批评,在下将不胜感激! 
复制代码
阅读全文
0 0
原创粉丝点击