字符串广义表和多叉树、普通树以及多叉树、普通树和广义表链表表示的相互转换

来源:互联网 发布:非诚勿扰李纳的淘宝店 编辑:程序博客网 时间:2024/06/16 12:22

程序用string对象接受广义表字符串的输入并将其转换为多叉树,然后将该多叉树转换为字符串广义表输出

#include "stdafx.h"#include <iostream>#include <string>#include <vector>using namespace std;class Knode   //k叉树节点{public:char data;  //节点数据域Knode **p;  //指向各子节点指针数组Knode(int k, char ch);};Knode::Knode(int k, char ch = '\0')  //节点初始化,k即为分叉数{data = ch;p = new Knode *[k]();}class Gennode{public:int numnode;Knode *ptr;Gennode(Knode *p) :ptr(p), numnode(-1) {}};class Path     //辅助k叉树遍历过程的类型{public:Knode *current;  //已遍历路径上k叉树节点的指针int direction;   //从当前节点前往其子节点的方向Path(Knode *ptr, int d) :current(ptr), direction(d) {}};int Search(Knode *ptr, int d, const int k);int Enable(Knode *ptr, int m);              //参考我之前写的K叉树运算的文章int maxlength(string &glist);    //求广义表glist子表最大长度,即为k叉树分叉树kint main(){string glist;cout << "请输入广义表的字符串形式" << endl;cin >> glist;Knode *ptr = nullptr; vector<Gennode> stack; int k = maxlength(glist);for (auto i = glist.cbegin(); i != glist.cend(); ++i) //从左至右扫描广义表{if (*i == '(')  //左括号{if (i == glist.cbegin())  //第一个左括号{ptr = new Knode(k);   //新建根节点入栈Gennode temp(ptr);stack.push_back(temp);}else    //子表左括号{Knode *temp = new Knode(k);    //新建非叶子节点ptr->p[++stack[stack.size() - 1].numnode] = temp;   //连接至父节点ptr = temp;Gennode temp2(ptr);  //ptr指向新建节点并入栈stack.push_back(temp2);}}else{if (*i == ')')  //右括号,父节点在本层子节点建立并链接完毕{stack.pop_back();   //直接出栈if (stack.size() != 0)ptr = stack[stack.size() - 1].ptr; //ptr回溯至父节点}else{if (*i != ',')   //原子数据{Knode *temp = new Knode(k, *i);   //建立与原子数据对应子节点ptr->p[++stack[stack.size() - 1].numnode] = temp;   //链接至父节点}}}}//扫描完后ptr即为k叉树根节点指针cout << "已将字符串形式的广义表转换为K叉树" << endl;vector<Path> treestack;Knode *const dest = ptr;int d = 0;cout << "该K叉树对应的广义表形式为:" << endl;cout << "(";while (true){if (Search(ptr, d, k) == 0)     //遍历K叉树(参考我写的K叉树运算文章){if (ptr == dest){cout << ")";  //遍历完成输出最后的右括号break;}else{if (d == 0)   //叶子{if (ptr->data == '\0')  //K叉树该叶子对应空表{cout << "()";   //输出空表}else{cout << ptr->data;   //普通原子项,输出之}}else{cout << ")";   //以当前父节点为根节点的子树已转化为字符串广义表输出,所以输出最后的右括号treestack.pop_back();   //父节点对应的Path节点出栈}ptr = treestack[treestack.size() - 1].current;   //ptr回溯至当前父节点的父节点d = treestack[treestack.size() - 1].direction;   //d更新为父节点的父节点的对应于当前父节点的方向}}else{Knode *interval = nullptr;if (d == 0)  //抵达新的节点,该节点有子节点{if (ptr != dest)   //该节点不是根节点,其对应子表的左括号为输出,输出之cout << "(";Path temp(ptr, Search(ptr, d, k));  interval = ptr->p[temp.direction-1];  //参考我写的K叉树运算文章treestack.push_back(temp);}else{cout << ",";  //回溯至的父节点还有下一个子节点,输出下一子节点和其相邻子节点对应表元素之间的逗号treestack[treestack.size() - 1].direction = Search(ptr, d, k);interval = ptr->p[treestack[treestack.size() - 1].direction - 1];   //参考我写的K叉树运算文章}ptr = interval;   ////参考我写的K叉树运算文章d = 0;}}return 0;}int Search(Knode *ptr, int d, const int k){int m = d;for (m++; m <= k; m++){if (Enable(ptr, m) == 1)return m;}return 0;}int Enable(Knode *ptr, int m){if (ptr->p[m - 1] != nullptr)return 1;elsereturn 0;}int maxlength(string &glist){int maxlen = 0; vector<int> stack;   //记录每层子表长度的栈for (const auto &s : glist)  //遍历广义表{if (s == '('){if (stack.size() != 0)   //遇到非广义表本身的子表的左括号++stack[stack.size() - 1];   //该子表所属父表的表元素计数应加一stack.push_back(0);  //计数该子表表元素个数栈节点入栈}else if (s == ')')  //找到子表{if (stack[stack.size() - 1] > maxlen)maxlen = stack[stack.size() - 1];   //stack栈顶为子表表长,利用其更新子表最大长度stack.pop_back();   //出栈}else if (s != ',')   //原子项{++stack[stack.size() - 1];  //原子项所属子表的表元素计数加一}}return maxlen;   //返回最大长度}

运行结果:



程序接受字符串广义表的输入将其转化为链表表示,然后将链表表示转化为K叉树,再将K叉树转换为链表表示,最后将链表表示转换为字符串形式输出

#include "stdafx.h"#include <iostream>#include <vector>#include <string>using namespace std;class Knode{public:char data;Knode **p;Knode(int k, char ch);};Knode::Knode(int k, char ch='\0'){data = ch;p = new Knode *[k]();}class Path    {public:Knode *current;   int direction;  Path(Knode *ptr, int d) :current(ptr), direction(d) {}};struct Gen{int utype;union{int ref;struct Gen *hlink;char value;}info;struct Gen *tlink;Gen(int u);Gen(int u, char v);};Gen::Gen(int u) :utype(u), tlink(nullptr){if (u == 0)info.ref = 0;elseinfo.hlink = nullptr;}Gen::Gen(int u, char v) :utype(u), tlink(nullptr){info.value = v;}class Gennode{public:int numnode;Gen *ptr;Gennode(Gen *p) :ptr(p), numnode(-1) {}};int Search(Knode *ptr, int d, const int k);int Enable(Knode *ptr, int m);void suboutput(Gen *head);Gen * strtogen(string &glist);int maxlength(string &glist);int main(){string glist;cout << "请输入广义表的字符串形式" << endl;cin >> glist;Gen *ptr = strtogen(glist);//ptr初始化为指向广义表附加头结点的指针int k = maxlength(glist);bool TF = true; vector<Knode *> treestack; vector<Gennode> genstack;Knode *dest = nullptr;   //建树过程中指向树节点指针while (true){if (ptr != nullptr && (ptr->utype == 0 || ptr->utype == 1)){if (TF == true){if (ptr->utype == 0){Gennode temp(ptr);genstack.push_back(temp);dest = new Knode(k);         //当前节点为广义表附加头节点,建立对应K叉树根节点并将其指针入栈treestack.push_back(dest);ptr = ptr->tlink;}else{Knode *temp = new Knode(k);  //子表头节点,建立对应K叉树子节点dest->p[++genstack[genstack.size() - 1].numnode] = temp;   //将子节点链接至其父节点dest = temp;  //dest递进至子节点,并入栈treestack.push_back(dest);Gennode temp2(ptr);genstack.push_back(temp2);ptr = ptr->info.hlink;}}else{if (ptr->utype == 0)   //建树完毕退出break;else{ptr = ptr->tlink;TF = true;}}}else{if (ptr == nullptr)  //子表对应子树创建完毕{treestack.pop_back();   //出栈if (treestack.size() != 0)dest = treestack[treestack.size() - 1];  //栈不空则dest指针回溯至父节点ptr = genstack[genstack.size() - 1].ptr;genstack.pop_back();TF = false;}else{Knode *temp = new Knode(k, ptr->info.value); //建立与原子数据项对应的叶子节点dest->p[++genstack[genstack.size() - 1].numnode] = temp;  //叶子节点链接至父节点ptr = ptr->tlink;}}}  //此时dest即为根节点指针cout << "已将广义表链表表示转化为K叉树" << endl;vector<Path> treestack2; vector<Gen *> genstack2;Gen *p = new Gen(0);      //先分配广义表附加头节点并将其指针入栈genstack2.push_back(p);Knode *ptr1 = dest;int d = 0;while (true){if (Search(ptr1, d, k) == 0){if (ptr1 == dest){p = genstack2[genstack2.size() - 1];  //K叉树对应的广义表链表表示建立完毕,取栈顶指针赋予pbreak;   //p即为广义表附加头结点指针}else{if (d == 0){Gen *temp;if (ptr1->data == '\0')temp = new Gen(1);    //叶子对应子空表else    temp = new Gen(2, ptr1->data);  //叶子对应原子数据项if (p->utype == 1){if (TF == true) //为true表示从有分支的子节点前进至新的有分支子节点{               //然后从该子节点前进至的第一个节点就是当前ptr指向的树节点p->info.hlink = temp;  //这种情况下直接把叶子对应的链表节点链接在其父节点对应的子表中附加头节点后面if (temp->utype == 1)  //链接的链表节点代表空表,TF应置flaseTF = false;      }                        else                     //为false表示从有分支的子节点或表示空表的子节点回溯至父节点,然后再从父节点前进至当前叶子节点,两种情况下{                        //链接链表节点的方式是不同的p->tlink = temp;    //此时叶子对应的链表节点应该直接连接在同一层子表的最后一个节点后面}}else{p->tlink = temp;     //此时p要么指向广义表附加头节点要么指向同一层子表的最后一个原子节点,故链表节点直接链接在p后面if (temp->utype == 1)  //同上TF = false;}p = temp;d = treestack2[treestack2.size() - 1].direction;ptr1 = treestack2[treestack2.size() - 1].current;}else{p = genstack2[genstack2.size() - 1];genstack2.pop_back();treestack2.pop_back();d = treestack2[treestack2.size() - 1].direction;ptr1 = treestack2[treestack2.size() - 1].current;TF = false;}}}else{Knode *interval = nullptr;if (d == 0){if (ptr1 != dest)  //只有ptr1不指向根节点下面的操作才有意义{Gen *temp = new Gen(1);if (p->utype == 1){if (TF == true){p->info.hlink = temp;  //具体说明同上}else{p->tlink = temp;}}else{p->tlink = temp;}p = temp;genstack2.push_back(p);TF = true;}Path temp = Path(ptr1, Search(ptr1, d, k));interval = ptr1->p[temp.direction - 1];treestack2.push_back(temp);}else{treestack2[treestack2.size() - 1].direction = Search(ptr1, d, k);interval = ptr1->p[treestack2[treestack2.size() - 1].direction - 1];}ptr1 = interval;d = 0;}}cout << "已将K叉树转换为广义表链表表示"<<endl;cout << "链表表示对应的广义表形式为:"<<endl;suboutput(p);return 0;}
运行结果:



程序用string对象接受广义表字符串的输入并将其转换为普通树,然后将该普通树转换为字符串广义表输出

这里将树节点指针域改为vector对象,子节点链接至父节点的操作相应变为向vector对象添加指针的操作 这样做的好处是节省内存空间,简化代码,而且无需实现计算树的分叉数

#include "stdafx.h"#include <iostream>#include <string>#include <vector>using namespace std;class Knode{public:char data;vector<Knode *> p;  //这里由于为普通树,故树节点指针域改为存放knode指针的vector对象Knode(char ch);};Knode::Knode(char ch = '\0'){data = ch;}class Path{public:Knode *current;int direction;Path(Knode *ptr, int d) :current(ptr), direction(d) {}};int Search(Knode *ptr, int d);   //该函数有变动int maxlength(string &glist);int main(){string glist;cout << "请输入广义表的字符串形式" << endl;cin >> glist;Knode *ptr = nullptr; vector<Knode *> stack; for (auto i = glist.cbegin(); i != glist.cend(); ++i){if (*i == '('){if (i == glist.cbegin()){ptr = new Knode();stack.push_back(ptr);}else{Knode *temp = new Knode();ptr->p.push_back(temp);  //链接操作改用push_back实现ptr = temp;stack.push_back(ptr);}}else{if (*i == ')'){stack.pop_back();if (stack.size() != 0)ptr = stack[stack.size() - 1];}else{if (*i != ','){Knode *temp = new Knode(*i);ptr->p.push_back(temp);}}}}//扫描完后ptr即为普通树根节点指针cout << "已将字符串形式的广义表转换为普通树" << endl;vector<Path> treestack;Knode *const dest = ptr;int d = 0;cout << "该普通树对应的广义表形式为:" << endl;cout << "(";while (true){if (Search(ptr, d) == 0){if (ptr == dest){cout << ")";break;}else{if (d == 0){if (ptr->data == '\0'){cout << "()";}else{cout << ptr->data;}}else{cout << ")";treestack.pop_back();}ptr = treestack[treestack.size() - 1].current;d = treestack[treestack.size() - 1].direction;}}else{Knode *interval = nullptr;if (d == 0){if (ptr != dest)cout << "(";Path temp(ptr, Search(ptr, d));interval = ptr->p[temp.direction - 1];treestack.push_back(temp);}else{cout << ",";treestack[treestack.size() - 1].direction = Search(ptr, d);interval = ptr->p[treestack[treestack.size() - 1].direction - 1];}ptr = interval;d = 0;}}return 0;}int Search(Knode *ptr, int d){if (d < ptr->p.size())  //如果方向d小于ptr节点p对象容量,说明存在下一个可走方向,就是d+1return d + 1;elsereturn 0;}
运行结果:



程序接受字符串广义表的输入将其转化为链表表示,然后将链表表示转化为普通树,再将普通树转换为链表表示,最后将链表表示转换为字符串形式输出

#include "stdafx.h"#include <iostream>#include <vector>#include <string>using namespace std;class Knode{public:char data;vector<Knode *> p;Knode(char ch);};Knode::Knode(char ch = '\0'){data = ch;}class Path{public:Knode *current;int direction;Path(Knode *ptr, int d) :current(ptr), direction(d) {}};struct Gen{int utype;union{int ref;struct Gen *hlink;char value;}info;struct Gen *tlink;Gen(int u);Gen(int u, char v);};Gen::Gen(int u) :utype(u), tlink(nullptr){if (u == 0)info.ref = 0;elseinfo.hlink = nullptr;}Gen::Gen(int u, char v) :utype(u), tlink(nullptr){info.value = v;}int Search(Knode *ptr, int d);void suboutput(Gen *head);Gen * strtogen(string &glist);int main(){string glist;cout << "请输入广义表的字符串形式" << endl;cin >> glist;Gen *ptr = strtogen(glist);//ptr初始化为指向广义表附加头结点的指针bool TF = true; vector<Knode *> treestack; vector<Gen *> genstack;Knode *dest = nullptr;while (true){if (ptr != nullptr && (ptr->utype == 0 || ptr->utype == 1)){if (TF == true){if (ptr->utype == 0){genstack.push_back(ptr);dest = new Knode();treestack.push_back(dest);ptr = ptr->tlink;}else{Knode *temp = new Knode();dest->p.push_back(temp);dest = temp;treestack.push_back(dest);genstack.push_back(ptr);ptr = ptr->info.hlink;}}else{if (ptr->utype == 0)break;else{ptr = ptr->tlink;TF = true;}}}else{if (ptr == nullptr){treestack.pop_back();if (treestack.size() != 0)dest = treestack[treestack.size() - 1];ptr = genstack[genstack.size() - 1];genstack.pop_back();TF = false;}else{Knode *temp = new Knode(ptr->info.value);dest->p.push_back(temp);ptr = ptr->tlink;}}}  //dest即为根节点指针cout << "已将广义表链表表示转化为普通树" << endl;vector<Path> treestack2; vector<Gen *> genstack2;Gen *p = new Gen(0);genstack2.push_back(p);Knode *ptr1 = dest;int d = 0;while (true){if (Search(ptr1, d) == 0){if (ptr1 == dest){p = genstack2[genstack2.size() - 1];break;   //p即为广义表附加头结点指针}else{if (d == 0){Gen *temp;if (ptr1->data == '\0')temp = new Gen(1);elsetemp = new Gen(2, ptr1->data);if (p->utype == 1){if (TF == true){p->info.hlink = temp;if (temp->utype == 1)TF = false;}else{p->tlink = temp;}}else{p->tlink = temp;if (temp->utype == 1)TF = false;}p = temp;d = treestack2[treestack2.size() - 1].direction;ptr1 = treestack2[treestack2.size() - 1].current;}else{p = genstack2[genstack2.size() - 1];genstack2.pop_back();treestack2.pop_back();d = treestack2[treestack2.size() - 1].direction;ptr1 = treestack2[treestack2.size() - 1].current;TF = false;}}}else{Knode *interval = nullptr;if (d == 0){if (ptr1 != dest){Gen *temp = new Gen(1);if (p->utype == 1){if (TF == true){p->info.hlink = temp;}else{p->tlink = temp;}}else{p->tlink = temp;}p = temp;genstack2.push_back(p);TF = true;}Path temp = Path(ptr1, Search(ptr1, d));interval = ptr1->p[temp.direction - 1];treestack2.push_back(temp);}else{treestack2[treestack2.size() - 1].direction = Search(ptr1, d);interval = ptr1->p[treestack2[treestack2.size() - 1].direction - 1];}ptr1 = interval;d = 0;}}cout << "已将普通树转换为广义表链表表示" << endl;cout << "链表表示对应的广义表形式为:" << endl;suboutput(p);return 0;}
运行结果:


原创粉丝点击