数据结构算法C语言实现(十九)--- 5.5&5.6&5.7广义表
一.简述
传说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广义表的更多相关文章
- 数据结构(C语言版)-第4章 串、数组和广义表
补充:C语言中常用的串运算 调用标准库函数 #include<string.h> 串比较,strcmp(char s1,char s2) 串复制,strcpy(char to,char f ...
- 数据结构算法C语言实现(九)--- 拓展:由迷宫问题引申的AI贪吃蛇
一.简述 [开发中]由于期末时间有限,而且要用到后面的最短路径(可能),所以打算小学期在实现这一部分
- 数据结构算法C语言实现(二十)--- 6.3.1遍历二叉树
一.简述 二叉树的遍历主要是先序.中序.后序及对应的递归和非递归算法,共3x2=6种,其中后序非递归在实现上稍复杂一些.二叉树的遍历是理解和学习递归及体会栈的工作原理的绝佳工具! 此外,非递归所用的栈 ...
- 数据结构算法C语言实现(十二)--- 3.4循环队列&队列的顺序表示和实现
一.简述 空队列的处理方法:1.另设一个标志位以区别队列是空还是满:2.少用一个元素空间,约定以队列头指针在队尾指针下一位置上作为队列呈满的状态的标志. 二.头文件 //3_4_part1.h /** ...
- 数据结构算法C语言实现(十)--- 3.3栈与递归的实现
一.简介 汉诺塔问题是递归的一个典型例子,而且书上的讲解很详细,对理解C语言函数及函数传参的工作机制很有帮助,值得一看.而且,递归在我看来和分治.DP.贪心等一样是十分优美的思想,值得学习!!! 二. ...
- 数据结构算法C语言实现(八)--- 3.2栈的应用举例:迷宫求解与表达式求值
一.简介 迷宫求解:类似图的DFS.具体的算法思路可以参考书上的50.51页,不过书上只说了粗略的算法,实现起来还是有很多细节需要注意.大多数只是给了个抽象的名字,甚至参数类型,返回值也没说的很清楚, ...
- 数据结构算法C语言实现(六)---2.4一元多项式的表示及相加
一.简述 利用链表表示稀疏多项式,并基于之前的一些操作(编程实现上还是有所不同的)组合新的操作实现一元多项式的表示及相加. 二.ADT 抽象数据类型一元多项式的定义 ADT Polyomail{ 数据 ...
- 数据结构算法C语言实现(五)---2.3重新定义线性链表及其基本操作
一.简述 ...由于链表在空间的合理利用上和插入.删除时不需要移动等的优点,因此在很多场合下,它是线性表的首选存储结构.然而,它也存在着实现某些基本操作,如求线性表的长度时不如顺序存储结构的缺点:另一 ...
- 数据结构算法C语言实现(二)---2.3线性表的链式表示和实现之单链表
一.简述 [暂无] 二.头文件 #ifndef _2_3_part1_H_ #define _2_3_part1_H_ //2_3_part1.h /** author:zhaoyu email:zh ...
随机推荐
- 【转】加快网站访问速度——Yslow极限优化
Yslow是一套雅虎的网页评分系统,详细的列出了各项影响网页载入速度的参数,这里不做多说. 我之前就一直参考Yslow做博客优化,经过长时间的学习也算是有所收获,小博的YslowV2分数达到了94分( ...
- struts2 Result Type四个常用转跳类型
Result的四个常用转跳类型分别为 Dispatcher 用来转向页面,是Struts的默认形式 Redirect 重定向到一个URL Chain 用来处理Action链 RedirectAc ...
- SQL2005SP4补丁安装时错误: -2146233087 MSDTC 无法读取配置信息。。。错误代码1603的解决办法
是在安装slq2005sp3和sp4补丁的时候碰到的问题. 起先是碰到的错误1603的问题,但网上搜索的1603的解决办法都试过了,google也用了,外文论坛也读了,依然没有能解决这个问题. 其实一 ...
- 一次莽撞的行为:在phpmyadmin中修改MySQL root密码后无法操作数据库
一.手贱行为(✿◡‿◡) 在一次开发中通过xampp方式安装了PHP环境,需要操作数据库时通过phpmyadmin访问MySQL,在一次数据库操作时想起没有设置密码,于是直接在mysql数据库中的us ...
- 用 Linux自带的logrotate 来管理日志
大家可能都有管理日志的需要,比如定时压缩日志,或者当日志超过一定大小时就自动分裂成两个文件等.最近就接到这样一个小任务.我们的程序用的是C语言,用log4cpp的library来实现日志记录.但是问题 ...
- HTML问题集锦
[1]HTML5怎么设置滚动字幕 <marquee direction=up behavior=scroll loop=3 scrollamount=1 scrolldelay=10 align ...
- Form表单提交的简要方式
<html> <head> <meta name="viewport" content="width=device-width" ...
- C#,JavaScript两种语言 2048小游戏
<html> <head> <style type="text/css"> .haha { border-width: 2; font-size ...
- svn 的备份还原
备份脚本如下: #!/bin/bash ############################################################################### ...
- [转]浅谈jQuery EasyUI的属性设置
原文地址:http://www.easyui.info/archives/1664.html 对jQuery EasyUI有一定了解的话,应该知道基本上每一个组件都有一个"options&q ...