广义表的基本实现

来源:互联网 发布:rcpp软件 编辑:程序博客网 时间:2024/06/05 18:18

 广义表是线性表的一种推广。下边通过几个例子说明一下广义表:

A=(),A是一个空表,长度为0,深度为0.

B=(m),B中只有一个元素m,长度为1,深度为1.

C=(a,(b,c),d)有4个元素,长度为4,深度为2.

广义表的存储:


由于广义表的深度我们无法预知,当然不可以采用循环,所以用递归实现咯。

下边来看看实现代码:

#pragma once#include<iostream>using namespace std;#include<assert.h>enum Type{_HEAD_TYPE,_VALUE_TYPE,_SUB_TYPE};struct GeneralizedNode{Type _type;struct GeneralizedNode* _next;union{int _value;struct GeneralizedNode* _sublink;};GeneralizedNode(Type type){_type = type;}};class Generalized{public:Generalized():_head(NULL){}Generalized(char* str):_head(NULL){_head = Create(str);}~Generalized(){_Destroy(_head);}void Print(){_Print(_head);cout << endl;}size_t Size(){size_t count = _Size(_head);return count;}size_t Depth(){size_t depth = _Depth(_head);return depth;}Generalized(const Generalized& g){_head = _Copy(g._head);}//现代写法/*Generalized& operator=(Generalized g){std::swap(_head,g._head);return *this;}*///传统写法Generalized& operator=(const Generalized& g){if (this != &g){GeneralizedNode* head = _Copy(g._head);_Destroy(_head);_head = head;}return *this;}protected:void _Destroy(GeneralizedNode* _head){GeneralizedNode* cur = _head;while (cur){GeneralizedNode* del = cur;if (del->_type == _SUB_TYPE){_Destroy(cur->_sublink);}cur = cur->_next;delete del;}}GeneralizedNode* _Copy(GeneralizedNode* head){GeneralizedNode* cur = head->_next;//遍历原表GeneralizedNode* NewHead = new GeneralizedNode(_HEAD_TYPE);//指向新表GeneralizedNode* pre = NewHead;GeneralizedNode* NewNode;while (cur){if (cur->_type == _SUB_TYPE){NewNode = new GeneralizedNode(_SUB_TYPE);NewNode->_sublink = _Copy(cur->_sublink);pre->_next = NewNode;/*pre = NewNode;cur = cur->_next;*/}else if(cur->_type == _VALUE_TYPE){NewNode = new GeneralizedNode(_VALUE_TYPE);NewNode->_type = _VALUE_TYPE;NewNode->_value = cur->_value;//NewCur->_next = NewNode;pre->_next = NewNode;//NewCur = NewNode;/*NewCur = NewCur->_next;*//*pre = pre->_next;cur = cur->_next;*/}cur = cur->_next;pre = pre->_next;}pre->_next = NULL;return NewHead;}size_t _Depth(GeneralizedNode* head){GeneralizedNode* cur = head;size_t maxDepth = 1;while (cur){size_t depth  = 1;if (cur->_type == _SUB_TYPE){depth = _Depth(cur->_sublink)+1;if (depth > maxDepth){maxDepth = depth;}}cur = cur->_next;}return maxDepth;}void _Print(GeneralizedNode* head){cout << "(";GeneralizedNode* cur = head;while (cur){if (cur->_type == _VALUE_TYPE){cout << cur->_value;if (cur->_next != NULL){cout << ",";}cur = cur->_next;}else if (cur->_type == _SUB_TYPE){_Print(cur->_sublink);if (cur->_next != NULL){cout << ",";}cur = cur->_next;}else{cur = cur->_next;}}cout << ")";}size_t _Size(GeneralizedNode* &head){GeneralizedNode* cur = head;size_t count = 0;while (cur){if (cur->_type == _VALUE_TYPE){++count;cur = cur->_next;}else if (cur->_type == _SUB_TYPE)//子表{count += _Size(cur->_sublink);cur = cur->_next;}else{cur = cur->_next;}}return count;}bool isValue(char  c){//if (isalpha(c))//小写字母,大写字母if((c >= 'a'&&c<= 'z')|| (c >= 'A'&&c <= 'Z'))return true;elsereturn false;}GeneralizedNode* Create(char* &str){assert(*str == '(');str++;GeneralizedNode* head = new GeneralizedNode(_HEAD_TYPE);GeneralizedNode* prev = head;GeneralizedNode* cur = NULL;head->_next = cur;while (*str){if (isValue(*str))//字母字符{cur = new GeneralizedNode(_VALUE_TYPE);cur->_value = *str;prev->_next = cur;str++;prev = cur;}else if (*str == '('){GeneralizedNode* pLink = new GeneralizedNode(_SUB_TYPE);prev->_next = pLink;//cur = cur->_next;cur = Create(str);pLink->_sublink = cur;prev = pLink;}else if (*str == ')'){prev->_next = NULL;str++;return head;}else{str++;}}return head;}public:GeneralizedNode* _head;};void TestGeneralized(){Generalized s1("()");Generalized s2("(a,b)");Generalized s3("(a,b,(c,d))");Generalized s4("(a,b,(c,d),e)");Generalized s5("(a,b,(c,(),d),e)");Generalized s6(s3);s1 = s2;s1.Print();s2.Print();s3.Print();s4.Print();s6.Print();cout << s1.Size() << endl;cout << s2.Size() << endl;cout << s3.Size() << endl;cout << s4.Size() << endl;cout << s1.Depth() << endl;cout << s2.Depth() << endl;cout << s3.Depth() << endl;cout << s4.Depth() << endl;cout << s5.Depth() << endl;}


结点的定义中使用了枚举类型,原因如下:

结点有三种类型,值类型,头结点类型和子表 结点类型,而这三种结点公共的属性就是

每个结点都有自己的type(类型),也有自己的next域,值结点有自己的value,子表结

点有自己的_sublink,所以,这个可以定义成共用体类型,节省空间。

由于广义表需要用到递归,而类的成员函数最好不要递归(因为类的成员函数是内联函

数)

内联函数的特点:

在函数的调用处直接展开,减少了函数调用过程中的压栈开销所以,代码很长或者有

环,递归就尽量不要内联。

内联对于编译器而言只是一个建议,编译器会自动优化,如果内联函数内有循环或者

归,编译器会忽略内联。

inline必须和函数的定义放在一起。

下边再来简述一下operator=函数

两种实现办法:

传统的方法  ------避免自赋值;先构造,再释放(防止构造时申请空间失败) 

现代写法------一种是代码中写的那样

                     交换之后,原来空间的内容就会保存在那个形参变量中,离开作用域自动                            析构

              --------另一种是传引用。代码如下:

<pre name="code" class="cpp">GeneralizedNode* operator=(const Generalized& g){        if(&g != this)        {                Generalized<T>  tmp(g);                swap(_head,tmp._head);        }return *this;}




好了,广义表就到这里~~~

1 0
原创粉丝点击