一.简述

  传说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. IE6 P标签下DIV无法inline-block

    IE6 P标签下的DIV标签无法inline-block,使其触发了hasLayout属性再用csshack 使其inline还是不行,始终要换行 解决:把div标签替换成非div标签,比如span等 ...

  2. Python-01-基础

    一.安装Python 官方下载地址:https://www.python.org/downloads/ Windows可直接下载安装,安装时勾选自动配置环境变量即可. Linux/OS X默认装有Py ...

  3. Linux下源码安装ffmpeg及ffmpeg的简单使用说明

    一.编译安装 ffmpeg在安装时依赖的包和版本都很让人头疼,不同编译环境也各不相同.公司之前封装了一个又各种出错. 其实办法很简单,就是到官网一步一步按着做就行了:http://trac.ffmpe ...

  4. 【转】CSS Sprites教程大全(使用方法、工具介绍)

    什么是CSS Sprite CSS Sprite 又叫CSS精灵,是目前大型网站中经常运用的图片处理方式.它的原理很简单,将网站上零散的小图片(或图标)整合在一张大图上,再用CSS中“backgrou ...

  5. FineUI小技巧(1)简单的购物车页面

    起因 最初是一位 FineUI 网友对购物车功能的需求,需要根据产品单价和数量来计算所有选中商品的总价. 这个逻辑最好在前台使用JavaScript实现,如果把这个逻辑移动到后台C#实现,则会导致过多 ...

  6. IntelliJ IDEA,代码行宽度超出限制时自动换行

    转自:http://my.oschina.net/angerbaby/blog/471351 当我们使用IDE写代码时,为了保证代码的可阅读性和优雅性,通常会借助IDE的代码风格设置功能,令IDE智能 ...

  7. 谈谈关于Python里面小数点精度控制的问题

    基础 浮点数是用机器上浮点数的本机双精度(64 bit)表示的.提供大约17位的精度和范围从-308到308的指数.和C语言里面的double类型相同.Python不支持32bit的单精度浮点数.如果 ...

  8. MVC中使用Ajax提交数据 Jquery Ajax方法传值到action

    Jquery Ajax方法传值到action <script type="text/javascript"> $(document).ready(function(){ ...

  9. Sublime Text 必备插件

    收集网址:http://segmentfault.com/a/1190000002748032

  10. go -- 返回的json怎么去掉字段为空的字段啊