现在的位置: 首页 > 综合 > 正文

[数据结构]第五章-数组和广义表(读书笔记3)

2013年02月18日 ⁄ 综合 ⁄ 共 2661字 ⁄ 字号 评论关闭

第五章-数组和广义表

5.4 广义表
广义表是线性表的推广,也有人称其为列表(lists,用复数形式以示与统称的表list的区别)。
由于广义表中的数据元素可以具有不同的结构(或是原子,或是列表),因此难以用顺序存储结构表示,通常采用链式存储结构,每个元素可用一个结点表示。

(1)列表是一个多层次的结构。除空表的表头指针为空外,对任何非空列表,其表头指针均指向一个表结点,且该结点中的hp域指示列表表头,tp域指向列表表尾。
(2)任何一个非空列表其表头可能是原子,也可能是列表。而其表尾必定为列表。
(3)最高层的表结点个数即为列表的长度。

广义表运用在哪里:
(1)程序所需要的存储量事先不好预知,只能选用动态结构。
(2)使用中会出现频繁的插入与删除操作,链表的作用可以充分发挥。

typedef char AtomType; /* 定义原子类型为字符型 */
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是表结点的指针域,prt.hp和ptr.tp分别指向表头和表尾 */
	}a;
}*GList,GLNode; /* 广义表类型 */

Status InitGList(GList *L)
{ /* 创建空的广义表L */
	*L = NULL;
	return OK;
}

void DestroyGList(GList *L) /* 广义表的头尾链表存储的销毁操作 */
{ /* 销毁广义表L */
	GList q1,q2;
	if (*L){
		if ( (*L)->tag == ATOM ){
			free(*L);/* 删除原子结点 */
			*L = NULL;
		}
		else{ /* 删除表结点 */
			q1=(*L)->a.ptr.hp;
			q2=(*L)->a.ptr.tp;
			free(*L);
			*L = NULL;
			DestroyGList(&q1);
			DestroyGList(&q2);
		}
	}
}
Status CopyGList(GList *T,GList L)
{ /* 采用头尾链表存储结构,由广义表L复制得到广义表T。算法5.6 */
	if (!L){
		*T = NULL;
	}
	else{
		*T = (GList)malloc(sizeof(GLNode));/*建立表结点*/
		if(*T){
			exit(OVERFLOW);
		}
		(*T)->tag = L->tag;
		if(L->tag == ATOM){
			(*T)->a.atom = L->a.atom;/* 复制单原子 */
		}
		else{
			/* 复制广义表L->ptr.hp的一个副本T->ptr.hp */
			CopyGList(&(*T)->a.ptr.hp, L->a.ptr.hp);
			/* 复制广义表L->ptr.tp的一个副本T->ptr.tp */
			CopyGList(&(*T)->a.ptr.tp, L->a.ptr.tp);
		}
	}
	return OK;
}
int GListLength(GList L)
{ /* 返回广义表的长度,即元素个数 */
	int len = 0;
	if (!L){
		return 0;
	}
	if (L->tag == ATOM){
		return 1;
	}
	
	while(L){
		L = L->a.ptr.tp;
		len++;
	}
	return len;
}

int GListDepth(GList L)
{ /* 采用头尾链表存储结构,求广义表L的深度。算法5.5 */
	int max,dep;
	GList pp;
	if(!L){
		return 1; /* 空表深度为1 */
	}
	if(L->tag == ATOM){
		return 0; /* 原子深度为0 */
	}
	for(max = 0,pp = L; pp != NULL; pp = pp->a.ptr.tp){
		dep = GListDepth(pp->a.ptr.hp); /* 求以pp->a.ptr.hp为头指针的子表深度 */
		if(dep > max){
			max = dep;
		}
	}
	return max + 1; /* 非空表的深度是各元素的深度的最大值加1 */
}
Status GListEmpty(GList L)
{ /* 判定广义表是否为空 */
	if (L){
		return TRUE;
	}
	else{
		return FALSE;
	}
}
GList GetHead(GList L)
{ /* 取广义表L的头 */
	GList h,p;
	if(!L){
		printf("空表无表头!\n");
		exit(0);
	}
	p = L->a.ptr.tp;
	L->a.ptr.tp = NULL;
	CopyGList(&h, L);
	L->a.ptr.tp = p;
	return h;
}
GList GetTail(GList L)
{ /* 取广义表L的尾 */
	GList t;
	if(!L){
		printf("空表无表头!\n");
		exit(0);
	}
	CopyGList(&t, L->a.ptr.tp);
	return t;
}
Status InsertFirst_GL(GList *L,GList e)
{ /* 初始条件: 广义表存在 */
   /* 操作结果: 插入元素e作为广义表L的第一元素(表头,也可能是子表) */
	GList p = (GList)malloc(sizeof(GLNode));
	if(!p){
		exit(OVERFLOW);
	}
	p->tag = LIST;
	p->a.ptr.hp = e;
	p->a.ptr.tp = *L;
	*L = p;
	return OK;
}
Status DeleteFirst_GL(GList *L,GList *e)
{ /* 初始条件: 广义表L存在 */
	/* 操作结果: 删除广义表L的第一元素,并用e返回其值 */
	GList p;
	*e = (*L)->a.ptr.hp;
	p = *L;
	*L = (*L)->a.ptr.tp;
	free(p);
	return OK;
}
void Traverse_GL(GList L, void(*v)(AtomType))
{ /* 利用递归算法遍历广义表L */
	if(L){ /* L不空 */
		if(L->tag == ATOM){ /* L为单原子 */
			v(L->a.atom);
		}
		else{/* L为广义表 */
			Traverse_GL(L->a.ptr.hp, v);
			Traverse_GL(L->a.ptr.tp, v);
		}
	}
}
 void visit(AtomType e)
 {
   printf("%c ", e);
 }

int _tmain(int argc, _TCHAR* argv[])
{
	return 0;
}

 

抱歉!评论已关闭.