程序用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叉树分叉树k
int 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;
else
return 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; //返回最大长度
}
另有字符串广义表和多叉树相互转换的程序如下:C++
#include "pch.h"
#include <vector>
#include <stack>
#include <string>
#include <iostream>
using namespace std;
template <typename T>
struct MultiTreeNode
{
T *data_field;
vector<MultiTreeNode *> sub_node_ptr;
MultiTreeNode(size_t n, T *d) :sub_node_ptr(n, nullptr), data_field(d) {}
~MultiTreeNode() { delete data_field; }
};
template <typename T>
size_t searchD(MultiTreeNode<T> *current, size_t search_pos)
{
size_t temp = search_pos;
for (++temp; temp <= current->sub_node_ptr.size(); ++temp)
{
if (current->sub_node_ptr[temp-1] != nullptr)
return temp;
}
return 0;
}
void outPutComma(size_t before_num)
{
for (size_t i = 1; i <= before_num; ++i)
{
cout << ", ";
}
}
string charToStr(char t)
{
string s = " ";
s[0] = t;
return s;
}
template <typename T>
class Gennode
{
public:
int numnode;
MultiTreeNode<T> *ptr;
Gennode(MultiTreeNode<T> *p) :ptr(p), numnode(-1) {}
};
template <typename T>
MultiTreeNode<T> *strGenToTree(string &gen, int k)
{
MultiTreeNode<T> *ptr = nullptr; stack<Gennode<T>> work_stack;
char cur_char = '\0';
auto test = gen.cbegin();
++test;
for (auto i = gen.cbegin(); i != gen.cend(); ++i) //从左至右扫描广义表
{
if (*i == '(') //左括号
{
if (i == test) //第一个左括号
{
ptr = new MultiTreeNode<T>(k, new T(cur_char)); //新建根节点入栈
Gennode<T> temp(ptr);
work_stack.push(temp);
}
else //子表左括号
{
MultiTreeNode<T> *temp = new MultiTreeNode<T>(k, new T(cur_char)); //新建非叶子节点
ptr->sub_node_ptr[++work_stack.top().numnode] = temp; //连接至父节点
ptr = temp;
Gennode<T> temp2(ptr); //ptr指向新建节点并入栈
work_stack.push(temp2);
}
cur_char = '\0';
}
else
{
if (*i == ')') //右括号,父节点在本层子节点建立并链接完毕
{
if (cur_char != '\0')
{
MultiTreeNode<T> *temp = new MultiTreeNode<T>(k, new T(cur_char)); //建立与原子数据对应子节点
ptr->sub_node_ptr[++work_stack.top().numnode] = temp; //链接至父节点
cur_char = '\0';
}
work_stack.pop(); //直接出栈
if (work_stack.size() != 0)
ptr = work_stack.top().ptr; //ptr回溯至父节点
}
else
{
if (*i != ',' && *i != ' ') //原子数据
{
cur_char = *i;
}
else if (*i == ',')
{
if (cur_char != '\0')
{
MultiTreeNode<T>* temp = new MultiTreeNode<T>(k, new T(cur_char)); //建立与原子数据对应子节点
ptr->sub_node_ptr[++work_stack.top().numnode] = temp; //链接至父节点
cur_char = '\0';
}
}
else if (*i == ' ')
{
++work_stack.top().numnode;
}
}
}
}//扫描完后ptr即为k叉树根节点指针
return ptr;
}
template <typename T>
void output(MultiTreeNode<T> *root) //输出多叉树对应广义表形式
{
struct StackNode
{
MultiTreeNode<T> *ptr;
size_t index;
StackNode(MultiTreeNode<T>* p, size_t i) :ptr(p), index(i) {}
};
MultiTreeNode<T> *run = root;
size_t d = 0;
stack<StackNode> work_stack;
while (true)
{
size_t temp;
if ((temp = searchD(run, d)) == 0)
{
if (run == root)
{
if (d == 0)
{
cout << charToStr(*(run->data_field)) << "(";
}
cout << ")";
break;
}
else
{
if (d == 0)
{
cout << charToStr(*(run->data_field));
}
else
{
outPutComma(run->sub_node_ptr.size() - d);
cout << ")";
work_stack.pop();
}
run = work_stack.top().ptr;
d = work_stack.top().index;
}
}
else
{
if (d == 0)
{
cout << charToStr(*(run->data_field)) << "(";
for (size_t q = 1; q <= temp - 1; ++q)
{
cout << " ,";
}
work_stack.push(StackNode(run, temp));
}
else
{
outPutComma(temp - d - 1);
cout << ",";
work_stack.top().index = temp;
}
run = run->sub_node_ptr[temp - 1];;
d = 0;
}
}
}
int main()
{
int k = 3;
string glist = "a(b,c,d( , ,f(t,n, )))"; //每个子表必须包含k项,每项要么是子表,要么是原子项,要么是空格即空表,子表必须以单个字符开头,原子项必须为单个字符,括号要匹配,否则程序无法正确运行
MultiTreeNode<char>* ptr = strGenToTree<char>(glist, k);
cout << "已将字符串广义表转换为多叉树" << endl;
cout << "多叉树的字符串广义表形式为:";
output(ptr);
cout << endl;
return 0;
}
程序接受字符串广义表的输入将其转化为链表表示,然后将链表表示转化为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;
else
info.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叉树对应的广义表链表表示建立完毕,取栈顶指针赋予p
break; //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应置flase
TF = 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;
}
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;
else
return 0;
}
void suboutput(Gen *head)
{
Gen *ptr = head;
bool TF = true;
vector<Gen *> stack;
while (true)
{
if (ptr != nullptr && (ptr->utype == 0 || ptr->utype == 1)) //注意
{
if (TF == true)
{
stack.push_back(ptr);
cout << "(";
if (ptr->utype == 0) //注意
{
ptr = ptr->tlink;
}
else
{
ptr = ptr->info.hlink;
}
}
else
{
if (ptr == head)
break;
else
{
ptr = ptr->tlink;
TF = true;
}
}
}
else
{
if (ptr == nullptr)
{
cout << ")";
ptr = stack[stack.size() - 1];
if (ptr->utype != 0 && ptr->tlink != nullptr) //注意
cout << ",";
stack.pop_back();
TF = false;
}
else
{
cout << ptr->info.value;
ptr = ptr->tlink;
if (ptr != nullptr)
cout << ",";
}
}
}
cout << endl;
}
Gen * strtogen(string &glist)
{
Gen *ptr = nullptr; vector<Gen *> stack; bool TF;
for (auto i = glist.cbegin(); i != glist.cend(); ++i)
{
if (*i == '(')
{
if (i == glist.cbegin())
{
ptr = new Gen(0);
stack.push_back(ptr);
TF = true;
}
else
{
Gen *temp = new Gen(1);
if (ptr->utype == 1)
{
if (TF == true)
ptr->info.hlink = temp;
else
ptr->tlink = temp;
}
else
{
ptr->tlink = temp;
}
stack.push_back(temp);
TF = true;
ptr = temp;
}
}
else
{
if (*i == ')')
{
ptr = stack[stack.size() - 1];
stack.pop_back();
TF = false;
}
else
{
if (*i != ',')
{
Gen *temp = new Gen(2, *i);
if (ptr->utype == 1)
{
if (TF == true)
ptr->info.hlink = temp;
else
ptr->tlink = temp;
}
else
{
ptr->tlink = temp;
}
ptr = temp;
}
}
}
}
cout << "已将字符串形式转换为链表表示"<<endl;
return ptr;
}
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.pop_back();
}
else if (s != ',')
{
++stack[stack.size() - 1];
}
}
return maxlen;
}
广义表字符串形式和链表表示的相互转换
#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
using namespace std;
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;
else
info.hlink = nullptr;
}
Gen::Gen(int u, char v) :utype(u), tlink(nullptr)
{
info.value = v;
}
int main()
{
string glist;
cout << "请输入广义表的字符串形式" << endl;
cin >> glist;
Gen *ptr = nullptr; vector<Gen *> stack; bool TF; //stack辅助广义表遍历栈,存放子表附加头节点指针,TF标志返回上一层还是前进至本层
for (auto i = glist.cbegin(); i != glist.cend(); ++i) //遍历广义表
{
if (*i == '(')
{
if (i == glist.cbegin()) //广义表左括号
{
ptr = new Gen(0); //建立广义表附加头节点并入栈
stack.push_back(ptr);
TF = true;
}
else
{
Gen *temp = new Gen(1); //子表左括号,建立子表附加头节点
if (ptr->utype == 1) //上一个链接的广义表节点是子表附加头节点
{
if (TF == true)
ptr->info.hlink = temp; //此时应链接至上一个子表中,其附加头节点之后
else
ptr->tlink = temp; //否则是从上一子表回溯至本层子表,应链接至本层子表中上一子表附加头节点后
}
else
{
ptr->tlink = temp; //如果上一次链接的是原子项或分配广义表附加头节点,则直接链接到之后
}
stack.push_back(temp);
TF = true;
ptr = temp;
}
}
else
{
if (*i == ')') //本层子表已转换为链表表示
{
ptr = stack[stack.size() - 1]; //ptr回退至上一层中本层子表附加头节点
stack.pop_back();
TF = false;
}
else
{
if (*i != ',')
{
Gen *temp = new Gen(2, *i); //新建与原子项对应的广义表链表节点
if (ptr->utype == 1)
{
if (TF == true) //同上
ptr->info.hlink = temp;
else
ptr->tlink = temp;
}
else
{
ptr->tlink = temp;
}
ptr = temp;
}
}
}
} //扫描完毕此时ptr指向广义表链表表示的附加头结点,栈空
TF = true;
while (true) //遍历广义表链表形式
{
if (ptr != nullptr && (ptr->utype == 0 || ptr->utype == 1))
{
if (TF == true)
{
stack.push_back(ptr);
cout << "("; //找到子表或广义表附加头节点,此时应对应输出左括号
if (ptr->utype == 0)
{
ptr = ptr->tlink; //当前节点为广义表附加头节点,直接前进至本层下一节点
}
else
{
ptr = ptr->info.hlink; //为子表附加头节点,前进至子表中下一节点
}
}
else
{
if (ptr->utype == 0) //遍历完毕退出
break;
else
{
ptr = ptr->tlink; //从下一层子表回溯至本层子表,故继续让ptr前进至本层下一节点
TF = true;
}
}
}
else
{
if (ptr == nullptr) //已输出完子表除)外的所有项
{
cout << ")"; //应输出右括号
ptr = stack[stack.size() - 1]; //ptr回溯至本层子表上一层子表附加头节点
if (ptr->utype != 0 && ptr->tlink != nullptr) //注意,ptr不指向广义表附加头节点且有后继节点时应输出逗号
cout << ",";
stack.pop_back(); //出栈
TF = false;
}
else
{
cout << ptr->info.value; //输出原子项数据值
ptr = ptr->tlink;
if (ptr != nullptr) //有后继节点输出逗号
cout << ",";
}
}
}
cout << endl;
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+1
return d + 1;
else
return 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;
else
info.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);
else
temp = 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;
}
int Search(Knode *ptr, int d)
{
if (d < ptr->p.size())
return d + 1;
else
return 0;
}
void suboutput(Gen *head)
{
Gen *ptr = head;
bool TF = true;
vector<Gen *> stack;
while (true)
{
if (ptr != nullptr && (ptr->utype == 0 || ptr->utype == 1)) //注意
{
if (TF == true)
{
stack.push_back(ptr);
cout << "(";
if (ptr->utype == 0) //注意
{
ptr = ptr->tlink;
}
else
{
ptr = ptr->info.hlink;
}
}
else
{
if (ptr == head)
break;
else
{
ptr = ptr->tlink;
TF = true;
}
}
}
else
{
if (ptr == nullptr)
{
cout << ")";
ptr = stack[stack.size() - 1];
if (ptr->utype != 0 && ptr->tlink != nullptr) //注意
cout << ",";
stack.pop_back();
TF = false;
}
else
{
cout << ptr->info.value;
ptr = ptr->tlink;
if (ptr != nullptr)
cout << ",";
}
}
}
cout << endl;
}
Gen * strtogen(string &glist)
{
Gen *ptr = nullptr; vector<Gen *> stack; bool TF;
for (auto i = glist.cbegin(); i != glist.cend(); ++i)
{
if (*i == '(')
{
if (i == glist.cbegin())
{
ptr = new Gen(0);
stack.push_back(ptr);
TF = true;
}
else
{
Gen *temp = new Gen(1);
if (ptr->utype == 1)
{
if (TF == true)
ptr->info.hlink = temp;
else
ptr->tlink = temp;
}
else
{
ptr->tlink = temp;
}
stack.push_back(temp);
TF = true;
ptr = temp;
}
}
else
{
if (*i == ')')
{
ptr = stack[stack.size() - 1];
stack.pop_back();
TF = false;
}
else
{
if (*i != ',')
{
Gen *temp = new Gen(2, *i);
if (ptr->utype == 1)
{
if (TF == true)
ptr->info.hlink = temp;
else
ptr->tlink = temp;
}
else
{
ptr->tlink = temp;
}
ptr = temp;
}
}
}
}
cout << "已将字符串形式转换为链表表示" << endl;
return ptr;
}