广义表的创建

广义表是一种链式存储结构,广义表的表示方法有多种,在稍后的博文中我会依次给出各种广义表的算法代码实现。

首先简单的描述一下广义表的数据结构,广义表一般分为列表结点和原子结点。广义表中可以包含另一个广义表,这就使用广义表具有递归性,在下面的广义表创建中,就利用递归的思想进行创建。

对于广义表的表头表尾的理解:

比如广义表:A = (a,(b,c),((d,e,f),g)) ,其中B = (b,c)   C = ((d,e,f),g)    D = (d,e,f)

注意这里的表示方法: 小写字母表示原子结点,大写子表表示列表结点,其实也就是一个广义表

所以上面的表示方法也就可以写成: A = (a,B,C) 或者A = (a,B,(D,g))

广义表的表头可以是原子结点或者列表结点

广义表的表尾只能是列表结点

比如Head(A) = a           Tail(A) = ( (b,c),((d,e,f)g) ) 或者(B,C)

       Head(D) = d            Tail(D) = (e,f)

        Head(C) = (d,e,f) 或则D     Tail(C) = (g)

如果不是很清楚,查看下数据结构的书籍。总之记住广义表的表尾必须是表就行了,这就是为什么要加一对括号的原因。

比如一些特殊的广义表:

 空表 () 程序代号NIL    没有表头和表尾     长度为0

(())        这是一个非空表    表头为( )    表尾为 ( )    长度为1

程序中的广义表字符表示: "(a,(b,c),(e,f,(g)))"

#include <iostream>
#include <string.h>
#include <stdlib.h>
#define ERROR -1
#define OVER_FLOW 0
#define OK 1
#define MAX_STR_LEN 100
char hstr[MAX_STR_LEN] = {0};
char istr[MAX_STR_LEN] = {0};
typedef int Status; 
using namespace std;
typedef int AtomType;
typedef enum {ATOM, LIST} ElemTag;
typedef struct GLNode
{
	ElemTag tag;   //公共部分,用于区分原子和列表结点 
	union{  //共用体,共享同一片内存空间,大小由最大的元素决定 
		AtomType atom;  //原子结点的的值域 
		struct{
			struct GLNode * hp;  //列表的表头指针  
			struct GLNode * tp;  //列表的表尾指针 
		}prt;
	};
}*GList; 
/*建立广义表的思想:
	广义表结点分为列表结点和原子结点,当L为单个字符的时候,为原子结点。各个表中结点用逗号分隔
	建立广义表可以用递归思想实现,将一个表中的表头和表尾分别提取出来,分别建立表头和表尾的广义表,
	建立过程中注意将递归得出的广义表进行连接*/
void SubString(char *sub, char *p,int start,int end){
	char *temp = p+start;
	for(; temp <= p+end; temp++){
		*sub++ = *temp;
	}
	*sub = '\0';
}
void SplitHeadStr(char *&inputstr,char *&headstr){
	//将非空串inputstr分割成两个部分,headstr为第一个','之前的子串,inputstr为之后的字串
	int n = strlen(inputstr);
	int i = 0;
	int k = 0; //记录尚为配对的左括号的个数
	do{
		if(inputstr[i] == '(')
			k++;
		else if(inputstr[i] == ')')
			k--;
		i++;
	}while(i < n &&(inputstr[i] != ',' || k != 0));
	//该while循环的作用就是找出该表第一个表头逗号出的位置,如果没有逗号如: ((a,b))则会使i = n
	//注意该表已经脱去最外层的括号了
	
	if(i < n){
		SubString(headstr,inputstr,0,i-1);
		SubString(inputstr,inputstr,i+1,strlen(inputstr)-1);
	}else{
		strcpy(headstr,inputstr);
		inputstr = '\0';  //here equal sign the inputstr NULL
	}
}
Status CreateGList(GList &glist, char *str){
	if(strcmp(str, "()") == 0)
		glist =  NULL; //建立空表
	else{
		glist = (GList)malloc(sizeof(struct GLNode));  //新建一个表结点 
		if(glist == NULL)
			return OVER_FLOW;
		if(strlen(str) == 1){ //如果为单个字符,则创建原子结点 
			glist->tag = ATOM;;
			glist->atom = *str;
		}
		else{
			char *headstr = hstr;
			glist->tag = LIST;
			SubString(str,str, 1, strlen(str) - 2); //脱去最外边的括号 
			GList pointer = glist;
			do{ //创建子表 
				SplitHeadStr(str,headstr); //这里headstr为分割后的表头,str为分割后的表尾 
				char tstr[MAX_STR_LEN] = {0};
				strcpy(tstr,headstr);
				CreateGList(pointer->prt.hp,tstr);  //递归创建表头 
				if(str != NULL && strlen(str) != 0){  //如果表尾不为空的话 
					GList tailnode = (GList)malloc(sizeof(struct GLNode));
					if(pointer == NULL)
						return OVER_FLOW;
					tailnode->tag = LIST;  //广义表的表尾肯定是一张表 
					pointer->prt.tp = tailnode;
					pointer = tailnode; //set the tail of the current list
				} //end if
			}while(str != NULL && strlen(str) != 0);  //直到表尾为空NULL则退出 
			pointer->prt.tp = NULL;  //最后将表尾赋值为NULL 
		} //end else
	} 
	return OK;
} 
void OutputAtomNode(const GList mlist){
	GList pointer = mlist;  //利用递归思想输出广义表中的所有原子结点的值 
	do{
		GList temp = pointer->prt.hp;
		if(temp != NULL){  //递归输出表头中原子结点 
			if(temp->tag == ATOM)
				cout<<temp->atom<<endl;
			else
				OutputAtomNode(temp);
		}
		pointer = pointer->prt.tp;  // 指针指向表尾 
	}while(pointer != NULL);
}
int main(){
	strcpy(istr, "(a,(b,c),(e,f,(g)))");
	GList ml;
	CreateGList(ml,istr);	
	OutputAtomNode(ml); 
	return 0;
} 

教课书上创建广义链表的原始代码,在指针域上做了轻微的调整

Status CreateGList(GList &glist, char *str){
	if(strcmp(str, "()") == 0)
		glist =  NULL; //建立空表
	else{
		glist = (GList)malloc(sizeof(struct GLNode));  //新建一个表结点 
		if(glist == NULL)
			return OVER_FLOW;
		if(strlen(str) == 1){ //如果为单个字符,则创建原子结点 
			glist->tag = ATOM;;
			glist->atom = *str;
		}
		else{
			char *headstr = hstr;
			glist->tag = LIST;
			SubString(str,str, 1, strlen(str) - 2); //脱去最外边的括号 
			GList pointer = glist;
			GList tailnode = NULL;
			do{ //创建子表 
				SplitHeadStr(str,headstr); //这里headstr为分割后的表头,str为分割后的表尾 
				char tstr[MAX_STR_LEN] = {0};
				strcpy(tstr,headstr);
				CreateGList(pointer->prt.hp,tstr);  //递归创建表头 
				tailnode = pointer;
				if(str != NULL && strlen(str) != 0){  //如果表尾不为空的话 
					pointer = (GList)malloc(sizeof(struct GLNode));
					if(pointer == NULL)
						return OVER_FLOW;
					pointer->tag = LIST;  //广义表的表尾肯定是一张表 
					tailnode->prt.tp = pointer;  //set the tail of the current list
				} //end if
			}while(str != NULL && strlen(str) != 0);  //直到表尾为空NULL则退出 
			pointer->prt.tp = NULL;  //最后将表尾赋值为NULL 
		} //end else
	} 
	return OK;
} 


  • 11
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值