广义表的四个特征:(1)广义线性表;(2)元素复合性;(3)元素递归性;(4)元素共享性
广义表的上述四个特征对于他的使用价值和应用效果起到了很大的作用。广义表的结构相当灵活,它可以兼容线性表、数组、树和有向图等各种常用的数据结构。当二维数组的每行或每列作为子表处理时,二维数组就是一个广义表;如果限制广义表中元素的共享和递归,广义表和树对应;如果限制广义表的递归并允许数据共享,则广义表和图对应。
广义表的基本操作有:(1)创建一个广义表(我以头尾链表作为存储结构);(2)取表头;(3)取表尾;(4)求广义表深度;(5)求广义表长度,(5)求广义表原子个数;
(6)复制广义表等。
现将完整代码粘在这儿,便于以后复习。(代码可能有些许错误,如看到,望指出,谢谢!)
(一)、存储结构和函数定义(函数定义.h)
#include
#include
using namespace std;
#define MaxLength 60
typedef struct{
char str[MaxLength];
int length;
}SString;
typedef char AtomType;
typedef enum{ ATOM, LIST } ElemTag;//ATOM=0,表示原子,LIST=1,表示子表
typedef struct Node
{
ElemTag tag; //标志位tag用于区分元素是原子还是子表
union
{
AtomType atom; //AtomType是原子结点的值域,用户自己定义类型
struct
{
struct Node *hp, *tp; //hp指向表头,tp指向表尾
}ptr;
};
}*GList, GLNode;
//串函数定义
void StrAssign(SString *S, char cstr[]); //串赋值函数
int StrEmpty(SString S); //串判空函数
void StrCopy(SString *T, SString S); //串复制函数
void StrClear(SString *S); //串清空函数
int StrLength(SString S); //求串长函数
int StrCompare(SString S, SString T); //串比较函数
int StrInsert(SString *S, int pos, SString T);//串插入函数
int StrDelete(SString *S, int pos, int len); //串删除函数
int StrCat(SString *T, SString S); //串连接函数
int StrIndex(SString S, int pos, SString T); //串定位函数
int StrReplace(SString *S, SString T, SString V);//串替换函数
void StrPrint(SString S); //串输出函数
int SubString(SString *Sub, SString S, int pos, int len); //求子串函数
//广义表函数定义
void Error(char *s); //错误处理函数
void CreateList(GList *L, SString S); //创建头尾链表函数
void Init_GList(GList &GL); //初始化广义表函数
void CopyList(GList *T, GList L); //复制广义表函数
int GListLength(GList L); //求广义表长度函数
int GListDepth(GList L); //求广义表深度函数
int CountAtom(GList L); //求广义表中原子结点的数目函数
void PrintGList(GList L); //遍历输出广义表函数
void GetHead(GList L); //求广义表表头函数
void GetTail(GList L); //求广义表表尾函数
void DistributeString(SString *Str, SString *HeadStr);
//将非空字符串str分割成两部分:HSTR为第一个字符‘,’,之前的子串,SRE为之后的子串
(二).函数实现(函数实现.cpp)
#include "stdafx.h"
#include
#include
#include
#include"函数结构声明.h"
//串函数实现部分
//串赋值函数实现
void StrAssign(SString *S, char str[])
{
int i;
for (i = 0; str[i] != '\0'; i++)
S->str[i] = str[i]; //将常量cstr中的字符赋值给串S
S->length = i;
}
//判断串是否为空,串为空返回1,否则返回0
int StrEmpty(SString S)
{
if (S.length == 0)
return 1;
else
return 0;
}
//求串的长度操作
int StrLength(SString S)
{
return S.length;
}
//串的复制操作
void StrCopy(SString *T, SString S){
int i;
for (i = 0; istr[i] = S.str[i];
T->length = S.length; //将串S的长度赋值给串T
}
int StrCompare(SString S, SString T)
{ //串的比较操作
int i;
for (i = 0; iS->length){ //插入位置不正确,返回0
Error("插入位置不正确");
return 0;
}
if (S->length + T.length <= MaxLength){ //第一种情况,插入子串后串长≤MaxLength,即子串T完整地插入到串S中
for (i = S->length + T.length - 1; i >= pos + T.length - 1; i--) //在插入子串T前,将S中pos后的字符向后移动len个位置
S->str[i] = S->str[i - T.length];
for (i = 0; istr[pos + i - 1] = T.str[i];
S->length = S->length + T.length;
return 1;
}
else if (pos + T.length <= MaxLength){ //第二种情况,子串可以完全插入到S中,但是S中的字符将会被截掉
for (i = MaxLength - 1; i>T.length + pos - i; i--) //将S中pos以后的字符整体移动到数组的最后
S->str[i] = S->str[i - T.length];
for (i = 0; istr[i + pos - 1] = T.str[i];
S->length = MaxLength;
return 0;
}
else{ //第三种情况,子串T不能被完全插入到S中,T中将会有字符被舍弃
for (i = 0; istr[i + pos - 1] = T.str[i];
S->length = MaxLength;
return 0;
}
}
int StrDelete(SString *S, int pos, int len)
{//在串S中删除pos开始的len个字符
int i;
if (pos<0 || len<0 || pos + len - 1>S->length){
Error("删除位置不正确,参数len不合法");
return 0;
}
else{
for (i = pos + len; i <= S->length - 1; i++)
S->str[i - len] = S->str[i];
S->length = S->length - len;
return 1;
}
}
//串的连接操作
int StrCat(SString *T, SString S)
{
int i, flag;
if (T->length + S.length <= MaxLength){
for (i = T->length; ilength + S.length; i++)
T->str[i] = S.str[i - T->length];
T->length = T->length + S.length;
flag = 1;
}
else if (T->lengthlength; istr[i] = S.str[i - T->length];
T->length = MaxLength;
flag = 0;
}
return flag;
}
//截取子串操作
int SubString(SString *Sub, SString S, int pos, int len)
{
int i;
if (pos<0 || len<0 || pos + len - 1>S.length)
{
Error("参数pos和len不合法");
return 0;
}
else
{
for (i = 0; istr[i] = S.str[i + pos - 1];
Sub->length = len;
return 1;
}
}
//串的定位操作
int StrIndex(SString S, int pos, SString T) //BF算法实现
{
int i, j;
if (StrEmpty(T))
return 0;
i = pos;
j = 0;
while (i= T.length)
return i - j + 1;
else
return 0;
}
//串的替换操作
int StrReplace(SString *S, SString T, SString V)
{
//将S中所有的T替换为V
int i;
int flag;
if (StrEmpty(T))
return 0;
i = 0;
do{
i = StrIndex(*S, i, T);//找到T在S中的位置
if (i){
StrDelete(S, i, StrLength(T)); //删除找到的T
flag = StrInsert(S, i, V); //在i位置插入V
if (!flag)
return 0;
i += StrLength(V);
}
} while (i);
return 1;
}
//串的清空操作
void StrClear(SString *S){
S->length = 0;
}
//串的输出操作
void StrPrint(SString S){
int i;
for (i = 0; iptr.hp;
if (Head->tag == ATOM)
cout << "表头:" << Head->atom << endl;
else
{
cout << "表头:";
PrintGList(Head);
cout << endl;
}
}
void GetTail(GList L)
//求广义表的表尾操作
{
if (L == NULL) Error("空表不能取表头!");
GLNode *tail = L->ptr.tp;
cout << "表尾:";
PrintGList(tail);
cout << endl;
}
int GListLength(GList L)
//求广义表的长度操作
{
int length = 0;
GLNode *p = L;
if (p == NULL) return 0;
else
{
length = GListLength(p->ptr.tp);
}
return length + 1;
}
int GListDepth(GList L)
//求广义表的深度操作
{
int max, depth;
GLNode *p;
if (!L) //如果广义表非空,则返回1
return 1;
if (L->tag == ATOM) //如果广义表是原子,则返回0
return 0;
for (max = 0, p = L; p; p = p->ptr.tp) //逐层处理广义表
{
depth = GListDepth(p->ptr.hp);
if (maxtag == ATOM) return 1;
n1 = CountAtom(L->ptr.hp); //求表头中的原子数目
n2 = CountAtom(L->ptr.tp); //求表尾中的原子数目
return (n1 + n2);
}
void CopyList(GList *T, GList L)
//广义表的复制操作。由广义表L复制得到广义表T
{
if (!L) //如果广义表为空,则T为空表
*T = NULL;
else
{
*T = (GList)malloc(sizeof(GLNode)); //表L不空,为T建立一个表结点
if (*T == NULL)
Error("内存申请失败!");
(*T)->tag = L->tag;
if (L->tag == ATOM) //复制原子
(*T)->atom = L->atom;
else //递归复制子表
{
CopyList(&((*T)->ptr.hp), L->ptr.hp);
CopyList(&((*T)->ptr.tp), L->ptr.tp);
}
}
}
void DistributeString(SString *Str, SString *HeadStr)
//将串Str分离成两个部分,HeadStr为第一个逗号之前的子串,Str为逗号后的子串
{
int len, i, k;
SString Ch, Ch1, Ch2, Ch3;
len = StrLength(*Str); //len为Str的长度
StrAssign(&Ch1, ","); //将字符','、'('和')'分别赋给Ch1,Ch2和Ch3
StrAssign(&Ch2, "(");
StrAssign(&Ch3, ")");
SubString(&Ch, *Str, 1, 1); //Ch保存Str的第一个字符
for (i = 1, k = 0; i <= len&&StrCompare(Ch, Ch1) || k != 0; i++) //搜索Str最外层的第一个括号
{
SubString(&Ch, *Str, i, 1); //取出Str的第一个字符
if (!StrCompare(Ch, Ch2)) //如果第一个字符是'(',则令k加1
k++;
else if (!StrCompare(Ch, Ch3)) //如果当前字符是')',则令k减去1
k--;
}
if (i <= len) //串Str中存在',',它是第i-1个字符
{
SubString(HeadStr, *Str, 1, i - 2); //HeadStr保存串Str','前的字符
SubString(Str, *Str, i, len - i + 1); //Str保存串Str','后的字符
}
else //串Str中不存在','
{
StrCopy(HeadStr, *Str); //将串Str的内容复制到串HeadStr
StrClear(Str); //清空串Str
}
}
void CreateList(GList *L, SString S)
//采用头尾链表创建广义表
{
SString Sub, HeadSub, Empty;
GList p, q;
StrAssign(&Empty, "()");
if (!StrCompare(S, Empty)) //如果输入的串是空串则创建一个空的广义表
*L = NULL;
else
{
if (!(*L = (GList)malloc(sizeof(GLNode)))) //为广义表生成一个结点
Error("内存分配失败!");
if (StrLength(S) == 1) //广义表是原子,则将原子的值赋值给广义表结点
{
(*L)->tag = ATOM;
(*L)->atom = S.str[0];
}
else //如果是子表
{
(*L)->tag = LIST;
p = *L;
SubString(&Sub, S, 2, StrLength(S) - 2); //将S去除最外层的括号,然后赋值给Sub
do
{
DistributeString(&Sub, &HeadSub); //将Sub分离出表头和表尾分别赋值给HeadSub和Sub
CreateList(&(p->ptr.hp), HeadSub); //递归调用生成广义表
q = p;
if (!StrEmpty(Sub)) //如果表尾不空,则生成结点p,并将尾指针域指向p
{
if (!(p = (GLNode *)malloc(sizeof(GLNode))))
Error("内存分配失败!");
p->tag = LIST;
q->ptr.tp = p;
}
} while (!StrEmpty(Sub));
q->ptr.tp = NULL;
}
}
}
void PrintGList(GList L)
//输出广义表的元素
{
if (!L) cout << "()";
else
{
if (L->tag == ATOM)
cout << L->atom;
else
{
cout << '(';
GLNode *p = L;
while (p)
{
PrintGList(p->ptr.hp);
p = p->ptr.tp;
if (p) cout << ',';
}
cout << ')';
}
}
}
(三)主函数测试(主函数测试.cpp)
#include "stdafx.h"
#include
#include
#include"函数结构声明.h"
int _tmain(int argc, _TCHAR* argv[])
{
GList L, T;
SString S;
char str[60];
int depth, length;
cout << "请输入广义表:" << endl;
cin >> str;
StrAssign(&S, str); //将字符串赋值给串S
CreateList(&L, S); //由串创建广义表L
cout << "输出广义表L中的元素:" << endl;
PrintGList(L); //输出广义表中的元素
cout << endl;
cout << "广义表L表头是:" << endl;
GetHead(L);
cout << "广义表L表尾是:" << endl;
GetTail(L);
cout << "广义表L中的原子数目是:" << CountAtom(L) << endl;
length = GListLength(L); //求广义表的长度
cout << "广义表L的长度:" << length << endl;
depth = GListDepth(L); //求广义表的深度
cout << "广义表L的深度:" << depth << endl;
CopyList(&T, L);
cout << "由广义表L复制得到广义表T广义表T的元素为:" << endl;
PrintGList(T);
return 0;
}