广义表是线性表的一种推广。下边通过几个例子说明一下广义表:
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;
else
return 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;
}
好了,广义表就到这里~~~