一.简述

  传说Lisp的基本数据结构就是广义表,广义表也是具有典型递归属性的数据结构,此外,由于建表要处理字符串,用C语言处理起来也是一脸懵逼.....最后自己还想写一个将广义表还原成字符串的函数,一是使其可视化,而是验证算法5.6。花了不少功夫才写出来(强烈建议自己动手写一写),最后是借助树形结构的角度才找到一个不错的解决办法。按照《数据结构编程实验》的分类,数据结构无非线性结构、树状结构、图结构,可以说树是特殊的图(图的最小生成树),线性表示特殊的树。。。。。扯远了!

  二.头文件

  补充版字符串处理头文件

 //4_2_part1.h
/**
author:zhaoyu
*/
//2016-6-10
//----串的定长顺序存储表示----
#ifndef _4_2_PART1_H_
#define _4_2_PART1_H_
#include "head.h"
#define MAXSTRLEN 255//用户可以在255以内定义最大串长
//这语法还不是很熟悉
typedef unsigned char SString[MAXSTRLEN+];//0 号单元存放串的长度
int StrLength(SString T)
{
for (int i = ; i <= MAXSTRLEN; ++i)
{
if ('\0' == T[i])
{
return i-;
}
}
return MAXSTRLEN;
} /**
algorithm 4.2
*/
Status Concat(SString &T, SString S1, SString S2)
{
//用 T 返回由 S1 和 S2 连接而成的新串。
//若未截断,则返回 TRUE,否则返回 FALSE
Status uncut;
if (S1[] + S2[] < MAXSTRLEN)
{//未截断
int i = ;
for (i = ; i <= S1[]; ++i)
{
T[i] = S1[i];
}
for (i = ; i <= S2[]; ++i)
{
T[S1[]+i] = S2[i];
}
T[] = S1[] + S2[];
uncut = TRUE;
}
else if (S1[] < MAXSTRLEN)
{
int i = ;
for (i = ; i <= S1[]; i++)
{
T[i] = S1[i];
}
for (i = S1[]+; i <= MAXSTRLEN; i++)
{
T[i] = S2[i-S1[]];
}
T[] = MAXSTRLEN;
uncut = FALSE;
}
else
{
for (int i = ; i <= MAXSTRLEN; i++)
{
T[i] = S1[i];
}
T[] = S1[] = MAXSTRLEN;
uncut = FALSE;
}
return uncut;
}
/**
algorithm 4.3
*/
Status SubString(SString &Sub, SString S, int pos, int len)
{
//用 Sub 返回串 S 的第 pos 个字符起长度为 len 的字串
//其中, 1<= pos <<= SreLength(S) 且 0 <= len <= StrLength(S)-pos+1
if (pos < || pos > S[] || len < || len > S[]-pos+)
{
return ERROR;
}
for (int i = ; i <= len; i++)
{
Sub[i] = S[i+pos-];
}
Sub[len+] = '\0';
Sub[] = len;
return OK;
}
/**
add for chapter 5 / page 116.117
*/
Status StrCompare(SString S, SString T)
{
for (int i = ; i <= S[] && i <=T[]; i++)
{
if (S[i]-T[i] > ){
return ;
}
if (S[i]-T[i] < )
{
return -;
}
}
if (S[] == T[])
{
return ;
}
return S[]>T[]?:-;
}
Status StrEmpty(SString S)
{
if ( == StrLength(S))
{
return TRUE;
}
else
{
return FALSE;
}
}
Status StrCopy(SString &T, SString S)
{//健壮性并不够
for (int i = ; i <= S[]+; i++)
{
T[i] = S[i];
}
return OK;
}
Status ClearString(SString S)
{
S[] = ;
S[] = '\0';
return OK;
}
void PrintSString(SString T)
{
//if(T[])
for (int i = ; i <= T[]; ++i)
{
printf("%c", *(T+i));
}
printf("\n");
}
#endif

4_2_part1.h

 //5_5.h
/**
author:zhaoyu
date;2016-6-16
*/
//----广义表的头尾链表存储表示----
#include "4_2_part1.h"
#define AtomType char
typedef enum {ATOM, LIST} ElemTag;//ATOM==0:原子,LIST==1子表
typedef struct GLNode
{
ElemTag tag;//公共部分,用于区分原子结点和表节点
union{//原子结点和表节点的公共部分
AtomType atom;//atom 是原子结点的值域,AtomType由用户定义
struct {struct GLNode *hp, *tp;}ptr;//ptr 是表结点
//的指针域,ptr.hp 和 ptr.tp 分别指向表头和表尾
};
}*GList;//广义表类型
/**
algorithm 5.5
*/
int GListDepth(GList L)
{//采用头尾链表存储结构,求广义表 L 深度
if (!L)
{
return ;//空表深度为 1
}
if (L->tag == ATOM)
{
return ;//原子深度为 0
}
int MAX = ;
for (GList pp = L; pp; pp = pp->ptr.tp)
{
int t = GListDepth(pp->ptr.hp);//求以 ptr.hp 为头指针的子表深度
MAX = MAX>t?MAX:t;
}
return MAX+;
}
/**
algorithm 5.8
*/
Status sever(SString &str, SString &hstr)
{//将非空串 str 分割成两部分:hsub为第一个','之前的字串,str 为之后的子串
int n = StrLength(str);
int i = , k = ;//k 记尚未配对的左括号的个数
char ch;
SString CH;
do{
++i;
SubString(CH, str, i, );
ch = CH[];
if ('(' == ch)
{
++k;
}
else if (')' == ch){
--k;
}
}while (i < n && (',' != ch || != k));
if (i < n)
{
SubString(hstr, str, , i-);
SubString(str, str, i+, n-i);
}
else
{
StrCopy(hstr, str);
ClearString(str);
}
} /**
algorithm 5.7
*/
Status CreateGList(GList &L, SString S)
{//采用头尾链表存储结构,由广义表的书写形式串 S 创建广义表 L,设emp="()"
GList q = NULL, p = NULL;
SString emp = { , '(', ')', '\0'};
SString sub, hsub;
if ( == StrCompare(S, emp))
{//创建空表
L = NULL;
}
else
{
if (!(L = (GList)malloc(sizeof(GLNode))))
{
exit(OVERFLOW);//建表结点
}
if ( == StrLength(S))
{//创建单原子广义表
L->tag = ATOM;
L->atom = S[];
}
else
{
L->tag = LIST;
p = L;
SubString(sub, S, , StrLength(S)-);
do{//重复建 n 个子表
sever(sub, hsub);//从 sub 中分离出表头串 hsub
CreateGList(p->ptr.hp, hsub);
q = p;
if (!StrEmpty(sub))
{//表尾不空
if (!(p = (GList)malloc(sizeof(GLNode))))
{
exit(OVERFLOW);
}
p->tag = LIST;
q->ptr.tp = p;
}//if
}while (!StrEmpty(sub));
q->ptr.tp = NULL;
}//else
}
}
/**
algorithm 5.6
*/
Status CopyGList(GList &T, GList L)
{//采用头尾链表存储结构,由广义表 L 复制得到广义表 T
if (!L)
{
T = NULL;
}
else
{
if (!(T = (GList)malloc(sizeof(GLNode))))
{
exit(OVERFLOW);
}
T->tag = L->tag;
if (ATOM == L->tag)
{
T->atom = L->atom;
}
else
{
CopyGList(T->ptr.hp, L->ptr.hp);
CopyGList(T->ptr.tp, L->ptr.tp);
}
}
return OK;
} /**
my code
*/
int cnt = ;
void PrintGList(GList L)
{
if (NULL == L)
{
printf("()");
}
else
{
if (ATOM == L->tag)
{
printf("%c", L->atom);
}
else
{
if (NULL == L->ptr.hp)
{
printf("(");
}
if (NULL != L->ptr.hp && LIST == L->ptr.hp->tag)
{
printf("(");
}
PrintGList(L->ptr.hp);
if (NULL != L->ptr.tp && LIST == L->ptr.tp->tag)
{
printf(",");
}
if (NULL == L->ptr.tp)
{
printf(")");
}
else
{
PrintGList(L->ptr.tp);
} }
}
}

5_5.h

  三.CPP文件

 #include "5_5.h"
int main(int argc, char const *argv[])
{
// freopen("out.txt", "w", stdout);
//test function sever SString s, t;
scanf("%s", s+);
s[] = StrLength(s);
sever(s, t);
printf("t:%s\n", t+);
printf("s:%s\n", s+); GList L = NULL, T = NULL;
SString S;
scanf("%s", S+);
S[] = StrLength(S);
printf("len: %d\n", S[]);
CreateGList(L, S);
printf("\nL--Depth\t%d\n", GListDepth(L));
CopyGList(T, L);
printf("\nT--Depth\t%d\n", GListDepth(T));
printf("T:\t");
PrintGList(T);
printf("\n");
return ;
}

5_5.cpp

  四.测试

  

  测试用例是书上的一个例子,其结构图及对应二叉树如下

  

  

数据结构算法C语言实现(十九)--- 5.5&5.6&5.7广义表的更多相关文章

  1. 数据结构(C语言版)-第4章 串、数组和广义表

    补充:C语言中常用的串运算 调用标准库函数 #include<string.h> 串比较,strcmp(char s1,char s2) 串复制,strcpy(char to,char f ...

  2. 数据结构算法C语言实现(九)--- 拓展:由迷宫问题引申的AI贪吃蛇

    一.简述 [开发中]由于期末时间有限,而且要用到后面的最短路径(可能),所以打算小学期在实现这一部分

  3. 数据结构算法C语言实现(二十)--- 6.3.1遍历二叉树

    一.简述 二叉树的遍历主要是先序.中序.后序及对应的递归和非递归算法,共3x2=6种,其中后序非递归在实现上稍复杂一些.二叉树的遍历是理解和学习递归及体会栈的工作原理的绝佳工具! 此外,非递归所用的栈 ...

  4. 数据结构算法C语言实现(十二)--- 3.4循环队列&队列的顺序表示和实现

    一.简述 空队列的处理方法:1.另设一个标志位以区别队列是空还是满:2.少用一个元素空间,约定以队列头指针在队尾指针下一位置上作为队列呈满的状态的标志. 二.头文件 //3_4_part1.h /** ...

  5. 数据结构算法C语言实现(十)--- 3.3栈与递归的实现

    一.简介 汉诺塔问题是递归的一个典型例子,而且书上的讲解很详细,对理解C语言函数及函数传参的工作机制很有帮助,值得一看.而且,递归在我看来和分治.DP.贪心等一样是十分优美的思想,值得学习!!! 二. ...

  6. 数据结构算法C语言实现(八)--- 3.2栈的应用举例:迷宫求解与表达式求值

    一.简介 迷宫求解:类似图的DFS.具体的算法思路可以参考书上的50.51页,不过书上只说了粗略的算法,实现起来还是有很多细节需要注意.大多数只是给了个抽象的名字,甚至参数类型,返回值也没说的很清楚, ...

  7. 数据结构算法C语言实现(六)---2.4一元多项式的表示及相加

    一.简述 利用链表表示稀疏多项式,并基于之前的一些操作(编程实现上还是有所不同的)组合新的操作实现一元多项式的表示及相加. 二.ADT 抽象数据类型一元多项式的定义 ADT Polyomail{ 数据 ...

  8. 数据结构算法C语言实现(五)---2.3重新定义线性链表及其基本操作

    一.简述 ...由于链表在空间的合理利用上和插入.删除时不需要移动等的优点,因此在很多场合下,它是线性表的首选存储结构.然而,它也存在着实现某些基本操作,如求线性表的长度时不如顺序存储结构的缺点:另一 ...

  9. 数据结构算法C语言实现(二)---2.3线性表的链式表示和实现之单链表

    一.简述 [暂无] 二.头文件 #ifndef _2_3_part1_H_ #define _2_3_part1_H_ //2_3_part1.h /** author:zhaoyu email:zh ...

随机推荐

  1. c++ 指针(二)

    函数指针 可以使用算法的地址传递给方法,传递之前要先完成以下工作 1.获取函数的地址 2.声明一个函数指针 3.使用函数指针来调用函数 1.获取函数的地址,只要使用函数名就可以 Fun2(Fun1); ...

  2. js的Object和Function

    自己闲的没事干,自己想通过js的了解写一个Function和Object之间的关系,可以肯定的是我写错了,但是希望可以有所启发. Function和Object Function.__proto__ ...

  3. Servicestack IRequestLogger获取 IHttpRequest

    我在 ServiceStack里实现了 Logging 中的请求与返回,同时我想在IRequestLogger.Log() 方法中获取 IHttpRequest . IRequestContext 并 ...

  4. Eclipse利用Maven2搭建SpringMVC框架的Web工程

    一.准备工作: 下载apache-maven--> 配置Maven_home -->下载Eclipse Maven插件 二.新建工程:   选择新建Maven Project  arche ...

  5. linux 权限

    ls -la 查看文件 drwxr-xr-x 2 root root 4096 ...... 第一个d:代表目录:-代表文件 后面三个一组:r:读:w:写:x:执行 第一个root 代表所属用户: 第 ...

  6. android listview 的监听事件

    今天遇到了一个比较让我头疼的问题,不过追根揭底只是我对listview理解的不够透彻罢了, 闲言少叙,说说我遇到的问题吧: 上篇随笔我写了关于listview的使用,如果你也已经写好了列表那么恭喜这一 ...

  7. 【Alpha版本】冲刺阶段——Day 6

    我说的都队 031402304 陈燊 031402342 许玲玲 031402337 胡心颖 03140241 王婷婷 031402203 陈齐民 031402209 黄伟炜 031402233 郑扬 ...

  8. jax-ws开发总结

    服务端开发步骤: 1.定义SEI,即java中的接口 2.定义SEI的实现类,使用@webservice注解标记它是一个webservice服务类 3.发布服务 客户端开发步骤:使用jdk的servi ...

  9. spring mvc mybatis 搭建 配置文件信息

    参考地址:http://blog.csdn.net/fox_lht/article/details/16952683 shiro集成:http://www.cnblogs.com/miskis/p/5 ...

  10. Swift基础--Swift中的分类以及在分类中扩展init方法的注意事项

    Swift中的分类 1.创建一个空的swift文件 2.关键字extension,格式: extension 要扩展的类名 {} extension UIButton { } Swift中扩展init ...