33. 蛤蟆的数据结构笔记之三十三广义表实现二

33. 蛤蟆的数据结构笔记之三十三广义表实现二

本篇名言:
希望是附丽于存在的,有存在,便有希望,有希望,便是光明。--鲁迅”

我们继续来看下广义表的其他代码实现。代码均来自网络,解释来自蛤蟆,均亲测可行。

欢迎转载,转载请标明出处:

1.  广义表实现二

1.1         main

创建两个链表的指针head和L。

输入一个字符串,调用GLCreate函数创建广义表。显示,获取头表,尾表,输出长度,深度,原子个数,复制列表,Merge列表,遍历,比较广义表操作。

如下图1:

代码如下:

int main()

{

chars[MAXSIZE],a[MAXSIZE];

GListhead;

GListL;

printf("pleaseinput a string:");

scanf("%s",s);

head =GLCreate(s);

DisplayList(head);

printf("\n");

printf("TheHead is:");

DisplayList(GetHead(head));

printf("\n");

printf("TheTail is: ");

DisplayList(GetTail(head));

printf("\n");

printf("TheLength is %d\n",Length(head));

printf("TheDepth is %d\n",Depth(head));

printf("TheAtom number is %d\n",CountAtom(head));

printf("Copythe List:\n");

CopyList(&L,head);

DisplayList(L);

printf("\n");

printf("Mergethe List\n");

Merge(&L,head);

DisplayList(L);

printf("\n");

printf("PreOrder:");

PreOrder(head);

printf("\n");

printf("inputa string:");

scanf("%s",a);

L =GLCreate(a);

DisplayList(L);

printf("Eqaul ");

DisplayList(head);

printf(":");

if(Equal(L,head)) printf("yes!\n");

elseprintf("no!\n");

return0;

}

1.2         定义结构体

定义结构体,同实现一

typedef
struct
GLNode

{

ElemTagtag;

union

{

AtomType  atom;

struct GLNode*hp;

}atom_hp;

struct GLNode*tp;

}GLNode,*GList;

1.3         GLCreate

根据输入的字符串,建立广义表,成功则返回建立的广义表的表头,否则,返回NULL。

具体过程是这个样子的,先创建变量p,q,r,head。 然后先获取输入字符串的长度,对比字符串是否为“()”,以及字符串长度是否为0,如果满足其中之一,直接设置head=NULL,并返回head。

如果字符串长度为1,那么创建一个原子节点,并返回。

如果其他情况,创建一个head节点,设置tag为1,复制给p。然后将除去()之外的字符串赋值给substr临时变量。

然后取出substr的表头,让p指向这个表头,然后赋值给q. 接着计算剩余字符串的长度,如果大于0,则创建一个节点p,让q指向p. 根据len 是否大于零,继续取出表头进行循环。最后返回head.

PS:函数更多的是功能的实现,所以输入需要当前使用的朋友自己把关。原子节点也是一个字符。

1.4         Disastr

分离出广义表中表头部分,分离后剩下的字符串,不包括逗号

具体描述:

输入两个字符串的指针s,hstr。如果*s不为NULL且不是’,’ 或者K不为0,则进入第一个循环,判断是否*s为’(‘,如果是则K++. 如果是‘)’,则K- -。(K是括号计数器)

如果*s 为‘,’并且k不为0 或者 *s不为’,’ ,将*s赋值给hstr.

然后将剩余的留给rstr并通过s指针返回。

void Disastr(char *s,char
*hstr)

{

inti,j,k,r;

charrstr[MAXSIZE];

i=j=k=0;

while(s[i]&& (s[i] !=
‘,‘|| k))

{

if (s[i]==
‘(‘) {  k++ ; }        // k
作为括号计数器

else if (s[i]==
‘)‘) {k--;}

if (s[i]!=
‘,‘ || s[i]==
‘,‘ && k)

{

hstr[j]= s[i];

i++;

j++;

}

}

hstr[j]= ‘/0‘;

if (s[i]==
‘,‘) {i++;}

r=0;

while(s[i])                
// 处理剩余的表尾部分

{

rstr[r]=
s[i];

r++;

i++;

}

rstr[r]=
‘/0‘;

strcpy(s,rstr);

}

1.5         GetHead

取出广义表的表头部分,成功则返回广义表的表头,否则,返回空或退出。

具体描述:

如果为空,则返回NULL,如果tag为0,则退出,否则返回指针。

1.6         GetTail

取出广义表的表尾部分,成功返回广义表的表尾部分,否则,返回空或者退出。

1.7         DisplayList

打印广义表。

1.8         Length

求出广义表的长度,返回广义表的长度。

1.9         Depth

求得广义表的深度,求广义表的深度。

1.10    CountAtom

统计原子结点的个数。

1.11    CopyList

完成广义表的复制,将res复制到dest中,成功返回1,否则,返回0

1.12    Merge

合并广义表,如果p为空,则申请空间,将q复制到p中。

例如:((a,b),c) 和(a,b)合并之后为:((a,b),c,a,b)

算法描述:先找到第一个广义表的最后一个结点,将其链到第二个广义表的首元素即可

1.13    PreOrder

类似二叉树的先序遍历遍历广义表L

例如(a,(b,(c),d))结果为:a,b,c,d

L若为原子结点,显示该数据,递归调用遍历后续元素。

L是子表结点,递归调用遍历该子表,遍历后续元素。

1.14    Equal

判断两个广义表是否相等,相等,返回1,否则,返回0

相等的定义:两个广义表具有相同的存储结构,对应的原子结点的数据域也相等

1.15   源码

#include
<stdio.h>

#include
<string.h>

#include
<stdlib.h>

#define
AtomType
char

#define
MAXSIZE  1024

#define
ElemTag
int

#define
OK       1

#define
ERROR    0

typedef
struct
GLNode

{

ElemTagtag;

union

{

AtomType  atom;

struct GLNode*hp;

}atom_hp;

struct GLNode*tp;

}GLNode,*GList;

//功能:分离出广义表中表头部分

//返回:分离后剩下的字符串,不包括逗号

void Disastr(char *s,char
*hstr)

{

inti,j,k,r;

charrstr[MAXSIZE];

i=j=k=0;

while(s[i]&& (s[i] !=
‘,‘|| k))

{

if (s[i]==
‘(‘) {  k++ ; }        // k
作为括号计数器

else if (s[i]==
‘)‘) {k--;}

if (s[i]!=
‘,‘ || s[i]==
‘,‘ && k)

{

hstr[j]= s[i];

i++;

j++;

}

}

hstr[j]= ‘\0‘;

if (s[i]==
‘,‘) {i++;}

r=0;

while(s[i])                
// 处理剩余的表尾部分

{

rstr[r]=
s[i];

r++;

i++;

}

rstr[r]=
‘\0‘;

strcpy(s,rstr);

}

//功能:根据输入的字符串,建立广义表

//返回:成功则返回建立的广义表的表头,否则,返回NULL

GLNode * GLCreate(char *s)

{

GLNode*p,*q,*r,*head;

charsubstr[MAXSIZE],hstr[MAXSIZE];//rstr[MAXSIZE];

intlen;

len =strlen(s);

if (!strcmp(s,"()")|| !len)  { head =
NULL;}    
// (1) 空表情况

else if(len == 1)                                     // (2)
原子情况

{

head= (GLNode *)malloc(sizeof(GLNode));      
// 建立一个新结点

if(!head)  return
NULL;

head->tag= 0;                                
//构造原子结点

head->atom_hp.atom= *s;

head->tp=
NULL;

}

else                                               // (3)
子表情况

{

head= (GLNode *)malloc(sizeof(GLNode));

if(!head) return
NULL;

head->tag= 1;

p= head;

s++;

strncpy(substr,s,len-2);                        
//剥去外层的()

substr[len-2]=
‘\0‘;

do

{

Disastr(substr,hstr);                       
//分离出表头

r= GLCreate(hstr);

p->atom_hp.hp= r;                          
//尾插法建表

q=p;

len= strlen(substr);

if(len > 0)

{

p= (GLNode*)malloc(sizeof(GLNode));

if(!p)
return NULL;

p->tag= 1;

q->tp=p;

}

}while(len > 0);

q->tp=NULL;

}

returnhead;

}

void DisplayList(GList
head)

{

GLNode*p,*q;

if(!head) return;

if (head->tag==0)

{

printf("%c",head->atom_hp.atom);

return;

}

printf("(");

if (head)

{

do

{

p=
head->atom_hp.hp;

q=
head->tp;

while(q && p && p->tag == 0)               
//  同一层的原子结点

{

printf("%c,",p->atom_hp.atom);

p= q->atom_hp.hp;

q= q->tp;

}

if(p && !p->tag)                          
//最后一个原子结点

{

printf("%c",p->atom_hp.atom);

break;

}

else                                       
//子表情况

{

if(!p) printf("()");

elseDisplayList(p);

if(q)  printf(",");

head =q;

}

}while (head);

printf(")");

}

}

//功能:取出广义表的表头部分

//返回:成功则返回广义表的表头,否则,返回空或退出

GList GetHead(GList
L)

{

if(!L) return (NULL);                   
// 空表无表头

if (L->tag== 0)  exit(0);                
// 原子结点不是表

else return (L->atom_hp.hp);

}

//功能:取出广义表的表尾部分

//返回:成功返回广义表的表尾部分,否则,返回空或者退出

GList GetTail(GList
L)

{

if(!L)
return (NULL);

if (L->tag== 0) exit(0);

else return (L->tp);

}

//功能:求出广义表的长度

//返回值:广义表的长度

int Length(GList
L)

{

intk=0;

GLNode*s;

if(!L)
return0;                    //空表的长度为零

if (L->tag== 0) exit(0);           
//原子不是表

s=L;

while(s)                            
//统计表的最上层的长度

{

k++;

s=s->tp;

}

returnk;

}

//功能:求得广义表的深度

//输入:需求深度的广义表的指针

int Depth(GList
L)

{

intd,max;

GLNode*s;

if(!L) return (1);           
// 空表的深度为 1

if (L->tag==0) 
return 0;       // 原子的深度为 0

s=L;

max=0;

while(s)                       
//递归求每个子表深度的最大值

{

d= Depth(s->atom_hp.hp);

if(d > max) max = d;

s= s->tp;

}

return(max+1);                 
//表的深度为子表深度加一

}

//功能:统计原子结点的个数

//输入:需统计的广义表指针

int CountAtom(GList
L)

{

intn1,n2;

if(!L)
return0;                   //空表无原子结点

if (L->tag==0)return1;           
// 原子结点

n1 =CountAtom(L->atom_hp.hp);

n2 =CountAtom(L->tp);

return(n1+n2);

}

//功能:完成广义表的复制,将res复制到dest中

//返回:成功返回1,否则,返回0

bool CopyList(GList *dest,GList
res)

{

if(!res) {*dest =NULL;return (OK);}

*dest =(GLNode*)malloc(sizeof(GLNode));

if(!*dest) return (ERROR);

(*dest)->tag=
res->tag;

if (res->tag==0)  (*dest)->atom_hp.atom=
res->atom_hp.atom;

else

{

CopyList(&(*dest)->atom_hp.hp,res->atom_hp.hp);

CopyList(&(*dest)->tp,res->tp);

}

return (OK);

}

//功能:合并广义表,如果p为空,则申请空间,将q复制到p中

//例如:((a,b),c)和(a,b)合并之后为:((a,b),c,a,b)

//算法描述:先找到第一个广义表的最后一个结点,将其链到第二个广义表的首元素即可

void Merge(GList *p,GLNode
*q)

{

GLNode*r;

if(!q)
return;       //  如果复制的是个空表,返回

if(!p)              
// p为空,申请空间

{

*p =(GLNode*)malloc(sizeof(GLNode));

if(!(*p))
return ;

(*p)->tag= 1;

}

else

{

if((*p)->tag)

{

r=*p;

while(r->tp)r=r->tp;            
//找到最后一个子表的表尾指针

if (q->tag)r->tp =
q;        // 修改表尾指针

}

}

}

//功能:类似二叉树的先序遍历遍历广义表L

//eg:例如(a,(b,(c),d))结果为:a,b,c,d

//算法描述:

//L若为原子结点,显示该数据,递归调用遍历后续元素,也即:write(L->atom_hp.atom);PreOrder(L->tp);

//L是子表结点,递归调用遍历该子表,遍历后续元素,也即:PreOrder(L->atom_hp.tp);PreOrder(L->tp);

void PreOrder(GList
L)

{

if (L)

{

if (L->tag==0)printf("%c ",L->atom_hp.atom);  
// 打印原子结点

else  PreOrder(L->atom_hp.hp);                 
// 往下遍历,类似二叉树中的左子树

if (L->tp)PreOrder(L->tp);                    
// 往右遍历,类似二叉树中的右子树

}

}

//
判断两个广义表是否相等,相等,返回1,否则,返回0

//
相等的定义:两个广义表具有相同的存储结构,对应的原子结点的数据域也相等

//算法描述:

//
形式:条件

//Equal(p,q) = Equal(p->tp,q->tp) ; p->tag= 0 && q->tag = 0 && p->atom_hp.atom = q->atom_hp.atom

//Equal(p,q) =Equal(p->atom_hp.hp,q->atom_hp.hp) && Equal(p->tp,q->tp) ;p->tag = 1 && q->tag = 1

//Equal(p,q) = false     ; p->tag = 0 && q->tag = 0p->atom_hp.atom != q->atom_hp.atom
或者p->tag *p->tag + q->tag*q->tag =1

//Equal(p,q) = false      ; p q
其中之一为NULL

bool Equal(GList
p,GList
q)

{

boolflags = true;

if(!p &&
q)flags = false;

if (p&& !q) flags =
false;

if (p&&
q)

{

if (p->tag== 0 &&
q->tag == 0 )

{

if (p->atom_hp.atom!=
q->atom_hp.atom)

flags=
false;

}

else if (p->tag== 1 &&
q->tag == 1)

{

flags= Equal(p->atom_hp.hp,q->atom_hp.hp);

}

elseflags = false;

if(flags) flags = Equal(p->tp,q->tp);

}

returnflags;

}

int main()

{

chars[MAXSIZE],a[MAXSIZE];

GListhead;

GListL;

printf("pleaseinput a string:");

scanf("%s",s);

head =GLCreate(s);

DisplayList(head);

printf("\n");

printf("TheHead is:");

DisplayList(GetHead(head));

printf("\n");

printf("TheTail is: ");

DisplayList(GetTail(head));

printf("\n");

printf("TheLength is %d\n",Length(head));

printf("TheDepth is %d\n",Depth(head));

printf("TheAtom number is %d\n",CountAtom(head));

printf("Copythe List:\n");

CopyList(&L,head);

DisplayList(L);

printf("\n");

printf("Mergethe List\n");

Merge(&L,head);

DisplayList(L);

printf("\n");

printf("PreOrder:");

PreOrder(head);

printf("\n");

printf("inputa string:");

scanf("%s",a);

L =GLCreate(a);

DisplayList(L);

printf("Eqaul ");

DisplayList(head);

printf(":");

if(Equal(L,head)) printf("yes!\n");

elseprintf("no!\n");

return0;

}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-07 10:54:05

33. 蛤蟆的数据结构笔记之三十三广义表实现二的相关文章

43. 蛤蟆的数据结构笔记之四十三最短路径之迪杰斯特拉(Dijkstra )算法

43. 蛤蟆的数据结构笔记之四十三最短路径之迪杰斯特拉(Dijkstra )算法 本篇名言:"辛勤的蜜蜂永没有时间悲哀.--布莱克" 这次来看下Dijkstra )算法.还是老方法,先原理,后实现.代码来自网络. 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47046031 1.  最短路径 最短路径问题是图论研究中的一个经典算法问题, 旨在寻找图(由结点和路径组成的)中两结点之间的最短路径. 管道铺设.线路安排

34. 蛤蟆的数据结构笔记之三十四树的概念

34. 蛤蟆的数据结构笔记之三十四树的概念 本篇名言:"过去属于死神,未来属于你自己.--雪莱" 本篇笔记开始我们要进入新的概念了,树!是不是有点小激动呢?让我们从概念开始吧 当然概念要理解,如果当前不能立刻理解,可以后续结合代码一起理解效果更佳. 1.  树型结构 之前我们学习的那么多,其实都是线性数据结构. 树 则不同,它是非线性结构. 树形结构指的是数据元素之间存在着"一对多"的树形关系的数据结构,是一类重要的非线性数据结构.在树形结构中,树根结点没有前驱结点

30. 蛤蟆的数据结构笔记之三十数组之厄拉多塞筛

30. 蛤蟆的数据结构笔记之三十数组之厄拉多塞筛 本篇名言:"勤劳远比黄金可贵. -- 萨迪" 欢迎转载,转载请标明出处: 1.  厄拉多塞 厄拉多塞是一位古希腊数学家,他在寻找素数时,采用了一种与众不同的方法:先将2-N的各数放入表中,然后在2的上面画一个圆圈,然后划去2的其他倍数:第一个既未画圈又没有被划去的数是3,将它画圈,再划去3的其他倍数:现在既未画圈又没有被划去的第一个数是5,将它画圈,并划去5的其他倍数--依次类推,一直到所有小于或等于N的各数都画了圈或划去为止.这时,表

13、蛤蟆的数据结构笔记之十三栈的应用之栈与递归之斐波那契数列

13.蛤蟆的数据结构笔记之十三栈的应用之栈与递归之斐波那契数列 本篇名言:"人生不是一支短短的蜡烛,而是一支由我们暂时拿着的火炬,我们一定要把它燃得." 继续递归的斐波那契数列问题. 欢迎转载,转载请标明出处: 1.  斐波那契数列 斐波那契数列,又称黄金分割数列,指的是这样一个数列:0.1.1.2.3.5.8.13.21.--在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2)(n≥2,n∈N*)在现代物理.准晶体结构.化学

37. 蛤蟆的数据结构笔记之三十七图的概念

37. 蛤蟆的数据结构笔记之三十七图的概念 本篇名言:"宿命论是那些缺乏意志力的弱者的借口.--罗曼? 罗兰" 又到了一个新概念,这次咱们来看 这个图,图一看给人一种凌乱的感觉.那么它在数据结构中又是什么呢? 欢迎转载,转载请标明出处: 1.  图的概念 图(graph)是一种比线性表.树更为复杂的数据结构.在线性表中,数据元素之间呈线性关系,即每个元素只有一个直接前驱和一个直接后继.在树型结构中,数据元素之间有明显的的层次关系,即每个结点只有一个直接前驱,但可有多个直接后继,而在图结

35. 蛤蟆的数据结构笔记之三十五遍历二叉树

35. 蛤蟆的数据结构笔记之三十五遍历二叉树 本篇名言:"冬天已经到来,春天还会远吗? --雪莱" 我们来看徐璈如何遍历二叉树. 欢迎转载,转载请标明出处: 1.  二叉树遍历 二叉树的遍历有三种方式,如下: (1)前序遍历(DLR),首先访问根结点,然后遍历左子树,最后遍历右子树.简记根-左-右. (2)中序遍历(LDR),首先遍历左子树,然后访问根结点,最后遍历右子树.简记左-根-右. (3)后序遍历(LRD),首先遍历左子树,然后遍历右子树,最后访问根结点.简记左-右-根. 2.

3、蛤蟆的数据结构笔记之三线性表单项链表实现

今天励志短语:"人生的价值,即以其人对于当代所做的工作为尺度." 昨天我们看了线性表的一些定义概念,今天来看下其中的单项链表代码如何实现. 1.  声明结构 如下声明一个指向结构的指针.(存放整数的节点,我们也可以根据需要创建字符的链表) typedef struct list_node *list_pointer; typedef struct list_node{ intdata; list_pointerlink; }; list_pointerptr = NULL; 2.  定

23、蛤蟆的数据结构笔记之二十三串的堆分配实现

23.蛤蟆的数据结构笔记之二十三串的堆分配实现 本篇名言:"人的价值是由自己决定的." 接下去是看下如何用C实现串. 欢迎转载,转载请标明出处: 1.  定义 定义结构体如下,一种字符数组,一个表示数组的长度.以一组地址连续的存储单元存放串值字符序列,但是他们的存储空间是在程序执行过程中动态分配而得. typedefstruct { charch[MAXLEN]; intlen; }SString; 2.  复制 将一个串内容复制到另一个结构体中区. SString StrCopy(S

42. 蛤蟆的数据结构笔记之四十二图的遍历之广度优先

42. 蛤蟆的数据结构笔记之四十二图的遍历之广度优先 本篇名言:"生活真象这杯浓酒 ,不经三番五次的提炼呵 , 就不会这样一来可口 ! -- 郭小川" 继续看下广度优先的遍历,上篇我们看了深度遍历是每次一个节点的链表是走到底的. 欢迎转载,转载请标明出处:http://write.blog.csdn.net/postedit/47029275 1.  原理 首先,从图的某个顶点v0出发,访问了v0之后,依次访问与v0相邻的未被访问的顶点,然后分别从这些顶点出发,广度优先遍历,直至所有的