广义表链表表示的删除:
从广义表附加头节点开始,逐一分离表头元素,是原子项就直接删除,是子表附加头节点则暂不删除,直接进入子表,再分离表头元素,然后用相同的方法删除,子表删除完成后向上回溯,继续删除上一层子表,如此不断进行直到整个广义表被删除为止
代码(C++)
#include <iostream> #include <vector> #include<string> 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; } Gen* strtogen(); int main() { Gen* ptr = strtogen(); //ptr初始化为广义表附加头结点指针 bool TF = true; vector<Gen*> stack; while (true) { if (ptr != nullptr && (ptr->utype == 0 || ptr->utype == 1)) { if (TF == true) { stack.push_back(ptr); if (ptr->utype == 0) { if (ptr->tlink == nullptr) { stack.pop_back(); TF = false; continue; } ptr = ptr->tlink; //拉链,分理出广义表附加头节点的下一待删除节点 stack.back()->tlink = ptr->tlink; } else { if (ptr->info.hlink == nullptr) TF = false; else { ptr = ptr->info.hlink; //拉链,分离出ptr指向的子表附加头节点在子表中的下一节点 stack.back()->info.hlink = ptr->tlink; } } } else { if (ptr->utype == 0) { delete ptr; break;//删除附加头节点,至此删除成功,退出 } else { delete ptr; stack.pop_back(); //删除子表附加头节点,子表删除成功 ptr = nullptr; } } } else { if (ptr != nullptr) { delete ptr; } if (stack.back()->utype == 0 && stack.back()->tlink == nullptr || stack.back()->utype != 0 && stack.back()->info.hlink == nullptr) { TF = false; ptr = stack.back(); if (stack.back()->utype == 0) { stack.pop_back(); } } else { if (ptr == nullptr) TF = true; if (stack.back()->utype == 0) { ptr = stack.back()->tlink; stack.back()->tlink = ptr->tlink; } else { ptr = stack.back()->info.hlink; stack.back()->info.hlink = ptr->tlink; } } } } //运行结束后ptr成为野指针,栈空,删除成功 cout << "链表形式的广义表删除成功!" << endl; return 0; } Gen* strtogen() { string glist; cout << "请输入广义表的字符串形式" << endl; cin >> glist; Gen* ptr = nullptr; vector<Gen*> stack; bool TF; auto i = glist.cbegin(); ++i; ptr = new Gen(0); stack.push_back(ptr); TF = true; for (; i != glist.cend(); ++i) { Gen* temp; if (*i == '(') { temp = new Gen(1); } else { if (*i == ')') { ptr = stack[stack.size() - 1]; stack.pop_back(); TF = false; continue; } if (*i != ',') { temp = new Gen(2, *i); } else continue; } if (ptr->utype == 1) { if (TF == true) ptr->info.hlink = temp; else ptr->tlink = temp; } else { ptr->tlink = temp; } if (*i == '(') { stack.push_back(temp); TF = true; } ptr = temp; } cout << "已将字符串形式的广义表转换为链表形式" << endl; return ptr; }广义表链表表示的复制:
就是按广度优先遍历的次序逐一复制,为方便复制,目标表指针总比原表遍历指针慢一步,原表遍历完成后复制就结束了
#include <iostream> #include <vector> #include <string> 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; } Gen* strtogen(); void suboutput(Gen* head); int main() { vector<Gen*> stack1;//源栈 vector<Gen*> stack2;//目标栈 Gen* ptr1 = strtogen(); //ptr1初始化为源广义表附加头节点指针 Gen* ptr2 = nullptr; //ptr2为目标广义表拷贝指针 bool TF = true; while (true) //循环开始,将源广义表链表表示拷贝为目标广义表链表表示 { bool t = (ptr1 != nullptr) && (ptr1->utype == 0 || ptr1->utype == 1); if (t || ptr1 != nullptr) { if (t == false || TF && ptr1->utype != 0 && ptr2->utype == 1) { if (t) { stack1.push_back(ptr1); } Gen* temp; if (t) { temp = new Gen(1); } else { temp = new Gen(2, ptr1->info.value); } if ((t || ptr2->utype == 1) && ptr2 == stack2.back()) { //ptr2新进至子表头节点,源广义表子表头节点链接至ptr2所指子表中头节点后 ptr2->info.hlink = temp; } else { ptr2->tlink = temp; } ptr2 = temp; if (t) { stack2.push_back(ptr2); ptr1 = ptr1->info.hlink; } else { ptr1 = ptr1->tlink; } } else { if (TF == false) { ptr2 = stack2.back(); stack2.pop_back(); if (ptr1->utype == 0) { break; //拷贝完毕,退出,ptr2为目标广义表头节点 } else { ptr1 = ptr1->tlink; TF = true; } } else { stack1.push_back(ptr1); if (ptr1->utype == 0) { ptr2 = new Gen(0); //拷贝广义表附加头节点,完成后ptr1递进 ptr2->info.ref = ptr1->info.ref; ptr1 = ptr1->tlink; } else { Gen* temp = new Gen(1); //由于ptr2指向目标广义表头节点或原子项,所以直接把待拷贝子表头节点链接于其后 ptr2->tlink = temp; ptr2 = temp; ptr1 = ptr1->info.hlink; } stack2.push_back(ptr2); } } } else { ptr2 = nullptr; ptr1 = stack1.back(); stack1.pop_back(); TF = false; } } /*while (true) { if (ptr1 != nullptr && (ptr1->utype == 0 || ptr1->utype == 1)) { if (TF == true) { stack1.push_back(ptr1); if (ptr1->utype == 0) { ptr2 = new Gen(0); //拷贝广义表附加头节点,完成后ptr1递进 ptr2->info.ref = ptr1->info.ref; ptr1 = ptr1->tlink; } else { Gen* temp = new Gen(1); if (ptr2->utype == 1) //需要把子表附加头节点拷贝至ptr2所指附加头节点后 { if (ptr2 == stack2.back()) //ptr2新进至子表头节点,源广义表子表头节点链接至ptr2所指子表中头节点后 ptr2->info.hlink = temp; else ptr2->tlink = temp; } else { ptr2->tlink = temp; //由于ptr2指向目标广义表头节点或原子项,所以直接把待拷贝子表头节点链接于其后 } ptr2 = temp; ptr1 = ptr1->info.hlink; } stack2.push_back(ptr2); } else { ptr2 = stack2.back(); stack2.pop_back(); if (ptr1->utype == 0) { break; //拷贝完毕,退出,ptr2为目标广义表头节点 } else { ptr1 = ptr1->tlink; TF = true; } } } else { if (ptr1 == nullptr) //子表拷贝完毕 { ptr2 = nullptr; ptr1 = stack1.back(); stack1.pop_back(); TF = false; } else { Gen* temp = new Gen(2, ptr1->info.value); //拷贝原子项 if (ptr2->utype == 1 && stack2[stack2.size() - 1] == ptr2) ptr2->info.hlink = temp; //如果ptr2新进至子表头节点,操作和上述相同 else ptr2->tlink = temp; //操作和上述相同 ptr2 = temp; ptr1 = ptr1->tlink; } } }*/ cout << "复制完成,复制后的广义表为:"; suboutput(ptr2); //输出复制后的广义表 return 0; } Gen* strtogen() { string glist; cout << "请输入广义表的字符串形式" << endl; cin >> glist; Gen* ptr = nullptr; vector<Gen*> stack; bool TF; auto i = glist.cbegin(); ++i; ptr = new Gen(0); stack.push_back(ptr); TF = true; for (; i != glist.cend(); ++i) { Gen* temp; if (*i == '(') { temp = new Gen(1); } else { if (*i == ')') { ptr = stack[stack.size() - 1]; stack.pop_back(); TF = false; continue; } if (*i != ',') { temp = new Gen(2, *i); } else continue; } if (ptr->utype == 1) { if (TF == true) ptr->info.hlink = temp; else ptr->tlink = temp; } else { ptr->tlink = temp; } if (*i == '(') { stack.push_back(temp); TF = true; } ptr = temp; } cout << "已将字符串形式的广义表转换为链表形式" << endl; return ptr; } 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->utype == 0) break; else { ptr = ptr->tlink; TF = true; } } } else { if (ptr == nullptr) { cout << ")"; ptr = stack.back(); 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; }基于广义表链表表示的比较:
两表指针同步动作,按广度优先遍历逐一比较,比较到某一处节点不等则广义表不等,否则会一直比较至遍历完整个广义表,此时两广义表相等
#include <iostream> #include <vector> #include <string> 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; } bool equals(Gen* ptr1, Gen* ptr2); //判断ptr1和ptr2指向的广义表节点是否相等的函数 Gen* strtogen(); int main() { vector<Gen*> stack1; vector<Gen*> stack2; Gen* ptr1 = strtogen(); //指向广义表1附加头节点 Gen* ptr2 = strtogen(); //指向广义表2附加头节点 //两指针同步动作 bool TF = true; int isequals = 1; //=1两广义表相等,否则不等 while (true) { if (ptr1 != nullptr && (ptr1->utype == 0 || ptr1->utype == 1)) { if (TF == true) { if (ptr1->utype == 0 || equals(ptr1, ptr2)) //比较表1子表头节点或指针和表2对应位置节点或指针 { stack1.push_back(ptr1); stack2.push_back(ptr2); if (ptr1->utype != 0) //附加头节点不必比较,跳过 { ptr1 = ptr1->info.hlink; ptr2 = ptr2->info.hlink; continue; } } else { isequals = 0; //不等,isequals置位,退出 break; } } else { if (ptr1->utype == 0) //比较完成,退出 break; else { TF = true; } } } else { if (equals(ptr1, ptr2)) { if (ptr1 == nullptr) { ptr1 = stack1[stack1.size() - 1]; //比较ptr1或其指向节点和ptr2或其指向节点 ptr2 = stack2[stack2.size() - 1]; stack1.pop_back(); stack2.pop_back(); TF = false; continue; } //比较ptr1或其指向的原子项和表2对应位置指针ptr2或其指向的节点 } else { isequals = 0; break; } } ptr1 = ptr1->tlink; ptr2 = ptr2->tlink; } if (isequals) cout << "两广义表相等"; else cout << "两广义表不等"; cout << endl; return 0; } bool equals(Gen* ptr1, Gen* ptr2) //ptr1和ptr2所指节点相等返回true否则返回false { if (ptr1 == nullptr && ptr2 == nullptr) return true; else { if (ptr1 != nullptr && ptr2 != nullptr) { if (ptr1->utype != ptr2->utype) return false; else { if (ptr1->utype == 1) return true; else { if (ptr1->info.value == ptr2->info.value) return true; else return false; } } } else { return false; } } } Gen* strtogen() { string glist; cout << "请输入广义表的字符串形式" << endl; cin >> glist; Gen* ptr = nullptr; vector<Gen*> stack; bool TF; auto i = glist.cbegin(); ++i; ptr = new Gen(0); stack.push_back(ptr); TF = true; for (; i != glist.cend(); ++i) { Gen* temp; if (*i == '(') { temp = new Gen(1); } else { if (*i == ')') { ptr = stack[stack.size() - 1]; stack.pop_back(); TF = false; continue; } if (*i != ',') { temp = new Gen(2, *i); } else continue; } if (ptr->utype == 1) { if (TF == true) ptr->info.hlink = temp; else ptr->tlink = temp; } else { ptr->tlink = temp; } if (*i == '(') { stack.push_back(temp); TF = true; } ptr = temp; } cout << "已将字符串形式的广义表转换为链表形式" << endl; return ptr; }