广义表
说到广义表,就必须知道它是个什么东西!!!! 今天就让我来详详细细的向大家来说说这个广义表。。。
广义表 是一种 数据结构 ,, ,这种表的结构是 链式存储的 ,,,,,是线性表的一种扩展。。。。
是 由 n个元素组成的有限序列。。。。
广义表 的定义可以说是递归的一种体现 ,,, , 因为在广义表 中不仅可以存在存数据,,,还可以存一个子表(广 义表 ),,,所以我们在这块只能使用递归来建立了。。。。。
下面是四种广义表
<1> A = ()
<2> B = (a,b)
<3> C = (a,b,(c,d))
<4> D = (a,b,(c,d),(e,(f),h))
<5> E = (((),()))
<2> B = (a,b)
<3> C = (a,b,(c,d))
<4> D = (a,b,(c,d),(e,(f),h))
<5> E = (((),()))
广义表的结构 我们制定的结构是这样的
这是上面的C广义表的结构
通过这个这个结构我们可以进而推断出来广义表的每个 节点的 内容
1、节点类型(判断这个节点有什么作用)
2、指针域(用来指向下一个节点的指针)
3、数据值(如果是值节点,要有这个值的数据)
4、链接指针(如果这个节点是子表节点,,,,需要有个指针指向字表的头)
这些内容 中
节点类型 包括三种 头节点 、、 值节点、、、 子表节点 这些类型我们可以 用 一个枚举量来表示(每个节点都有)
//定义一种枚举常量 ,, 用来表示节点类型
enum Type
{
HEAD,//表示节点类型为 头节点
VALUE,//表示节点类型为 值节点
SUB,//表示节点类型为 子表节点
};
指针域 是一个节点指针 指向一个 下个节点的指针(每个节点都有)
数据值 表示的值节点所表示的数据(只有值节点才有)
链接指针 指向一个子表节点的头 (只有子表节点才有)
因为 数据值 ,,, 与 链接指针 都只有 值节点 与 子表节点 才有
如果 我们为每一个节点都开辟一个一段空间,,,,要是节点的量过大的话 ,,,, 那么造成的浪费就严重了
所以 我们想到一个变量 union(共用体) 我们都知道这中 变量内部的成员共用的是同一段空间,
这样 我们可以根据节点类型的不同使用不同的变量 ,,, , ,既不会产生错误 ,,, ,也不会浪费空间。。
节点的定义代码
struct GeneralListNode//广义表节点
{
GeneralListNode* _next;//指针域
Type _type;//节点类型
union//匿名的共用体
{
GeneralListNode* _subLink;//链接指针
char _value;//数据值
};
GeneralListNode(Type type = HEAD,char value = ' ')//构造函数
:_next(NULL)
,_type(type)
{
if(_type == VALUE)//如果节点类型为值节点
{
_value = value;//将节点的数据给数据值
}
else//否则
{
_subLink= NULL;//节点的链接为NULL
}
}
};
针对一个广义表我们必须要实现的操作有
构造函数
拷贝构造
赋值运算符的重载
析构函数
求节点个数
求广义表的深度
为什么我把 构造函数 、、、 拷贝构造 、、、、赋值运算符重载、、、、析构函数 也说出来呢?????
因为 这里的这些函数我们都要自己实现 ,,,,为什么要自己实现呢???
因为 这里的节点存在子表节点 ,,,, ,如果直接实现的话 ,,,, 解药用到大量的循环 ,,,不仅很难实现
而且难理解 ,,,,并且还容易错 所以在这里我们对于这这些函数的实现要用到递归实现
下面是代码的实现
class GeneralList
{
typedef GeneralListNode Node;
public:
//构造函数
GeneralList(const char *s)//s表示是一个字符串
{
_head = CreatList(s); //调用自己实现的构造函数
}
GeneralList(const GeneralList& g)
{
_head = _Copy(g._head);
}
GeneralList& operator=(const GeneralList& g)
{
if(this != &g)
{
GeneralList tem(g);
std::swap(_head,tem._head);
}
return *this;
}
~GeneralList()
{
Distroy();
}
public:
void Distroy()
{
_Distroy(_head);
_head = NULL;
}
void Print()
{
_Print(_head);
cout<<endl;
}
//求节点的个数
size_t Size()
{
return _Size(_head);
}
//求广义表的深度
size_t Depth()
{
return _Depth(_head);
}
protected:
//判断字符串中每个字符 来决定,,,,是不是需要值节点
bool CheckValue(const char& s)
{
if((s >= '0'&&s <='9')
||(s >= 'a'&&s<='z')
||(s >= 'A'&&s<='Z'))
return true;
return false;
}
//自己实现的构造函数
Node * CreatList(const char* & s)
{
assert(*s =='(');//进来判断一下是不是需要建立广义表
Node * newhead = new Node(HEAD);//如果需要必须要先建立一个头节点
Node * tail = newhead;//定义tail节点指针 表示广义表最后一个节点
++s;
while(*s)
{
if(CheckValue(*s))//如果是值节点
{
tail->_next =new Node(VALUE ,*s);//最后一个节点 指针域 指向 一个新建立的值节点
tail = tail->_next;//最后一个节点后移
++s;//字符串向后
}
else if(*s == '(')//需要建立一个子表节点
{
tail ->_next = new Node(SUB);
tail =tail->_next;
tail->_subLink = CreatList(s); //子表的链接指针为一个新的广义表
}
else if(*s ==')')//表示广义表结束
{
++s;
return newhead;
}
else
{
++s;
}
}
return newhead;
}
void _Distroy(Node * head)//节点的销毁
{
Node * cur = head;
assert(cur->_type==HEAD);//判断是不是头节点
while(cur)
{
if(cur->_type ==SUB)//如果是子表节点
{
_Distroy(cur->_subLink);// 递归 将子表的链接指针销毁
Node *del = cur;
cur= cur->_next;
delete del;
}
else
{
Node *del = cur;
cur= cur->_next;
delete del;
}
}
}
size_t _Size(Node* head)//广义表节点的个数可以看成是 值节点的个数加上 子表节点的个数
{
Node * cur =head;
assert(cur->_type == HEAD);
size_t count = 0;
while(cur)
{
if(cur->_type ==VALUE)//如果是值节点 +1
{
++count;
cur =cur->_next;
}
else if(cur->_type ==HEAD)//头节点 跳过
{
cur = cur->_next;
}
else if(cur->_type ==SUB)//子表节点 递归
{
count += _Size(cur->_subLink);
cur= cur->_next;
}
else
{
assert(false);
}
}
return count;
}
size_t _Depth(Node *head)//深度为 1+上最大的子表深度
{
Node * cur = head;
assert(cur->_type == HEAD);
size_t maxdepth = 1;//1 为当前的深度
while(cur)
{
if(cur->_type== SUB)
{
size_t depth = 1+_Depth(cur->_subLink);
if(depth >maxdepth)
{
maxdepth = depth;// 广义表的深度就是当前的深度+上最大的子表的深度
}
}
cur = cur->_next;
}
return maxdepth;//如果当前的层 没有子表 ,深度为1
}
Node* _Copy(Node * head)//拷贝构造
{
Node *cur = head;
assert(cur->_type == HEAD);//判断是头节点的话 ,可进入
Node* newhead = new Node();//建立一个头节点
Node* tail = newhead;
cur = cur->_next;
while(cur)
{
if(cur->_type == VALUE)//如果是值节点
{
tail->_next =new Node(VALUE,cur->_value);//用值节点的数据来创建一个新的节点
tail = tail->_next;
cur = cur->_next;
}
else if(cur->_type ==SUB)
{
tail->_next = new Node(SUB);//如果遇到子表节点,,,,创建一个子表节点
tail = tail->_next;
tail->_subLink = _Copy(cur->_subLink);//递归复制建立一个广义表链接到子表节点的链接指针
cur = cur->_next;
}
else
{
cur = cur->_next;
}
}
return newhead;
}
void _Print(Node * head)
{
Node * cur = head;
assert(cur->_type ==HEAD);
while(cur)
{
if(cur->_type==VALUE)
{
cout<<cur->_value;
if(cur->_next)
{
cout<<',';
}
}
else if(cur->_type== HEAD)
{
cout<<'(';
}
else if(cur->_type== SUB)
{
_Print(cur->_subLink);
if(cur->_next)
{
cout<<',';
}
}
else
{
assert(false);
}
cur = cur->_next;
}
cout<<')';
}
protected:
Node * _head;
};
void TestGeneralList()
{
GeneralList g1("()");
g1.Print();
cout<<"g1.size = "<<g1.Size()<<endl;
cout<<"g1.Depth = "<<g1.Depth()<<endl;
GeneralList g2("(a,b)");
g2.Print();
cout<<"g2.size = "<<g2.Size()<<endl;
cout<<"g2.Depth = "<<g2.Depth()<<endl;
GeneralList g3("(a,b,(c,d))");
g3.Print();
cout<<"g3.size = "<<g3.Size()<<endl;
cout<<"g3.Depth = "<<g3.Depth()<<endl;
GeneralList g4("(a,b,(c,d),(e,(f),h))");
g4.Print();
cout<<"g4.size = "<<g4.Size()<<endl;
cout<<"g4.Depth = "<<g4.Depth()<<endl;
GeneralList g5("(((),()))");
g5.Print();
cout<<"g5.size = "<<g5.Size()<<endl;
cout<<"g5.Depth = "<<g5.Depth()<<endl;
GeneralList g6(g3);
g6.Print();
g5 = g4;
g5.Print();
}
大家要是看了还有什么不懂的地方 ,,,,或者写了有什么错误都可私聊我