《数据结构教程(李春葆主编 第五版)》第六章源代码—数组和广义表

稀疏矩阵的三元组表示算法

#include <stdio.h>
#define M 6
#define N 7
#define MaxSize  100         //矩阵中非零元素最多个数
typedef int ElemType;
typedef struct
{
	int r;					//行号
	int c;					//列号
	ElemType d;				//元素值
} TupNode;					//三元组定义
typedef struct 
{	
	int rows;				//行数
	int cols;				//列数
	int nums;				//非零元素个数
	TupNode data[MaxSize];
} TSMatrix;					//三元组顺序表

void CreatMat(TSMatrix &t,ElemType A[M][N])  //从一个二维稀疏矩阵创建其三元组表示
{
	int i,j;
	t.rows=M;t.cols=N;t.nums=0;
	for (i=0;i<M;i++)
	{
		for (j=0;j<N;j++) 
			if (A[i][j]!=0) 	//只存储非零元素
			{
				t.data[t.nums].r=i;t.data[t.nums].c=j;
				t.data[t.nums].d=A[i][j];t.nums++;
			}
	}
}

bool Value(TSMatrix &t,ElemType x,int i,int j)  //三元组元素赋值
{
	int k=0,k1;
	if (i>=t.rows || j>=t.cols)
		return false;				//失败时返回false
	while (k<t.nums && i>t.data[k].r) k++;					//查找行
	while (k<t.nums && i==t.data[k].r && j>t.data[k].c) k++;//查找列
	if (t.data[k].r==i && t.data[k].c==j)	//存在这样的元素
		t.data[k].d=x;
	else									//不存在这样的元素时插入一个元素
	{	
		for (k1=t.nums-1;k1>=k;k1--)
		{
			t.data[k1+1].r=t.data[k1].r;
			t.data[k1+1].c=t.data[k1].c;
			t.data[k1+1].d=t.data[k1].d;
		}
		t.data[k].r=i;t.data[k].c=j;t.data[k].d=x;
		t.nums++;
	}
	return true;						//成功时返回true
}

bool Assign(TSMatrix t,ElemType &x,int i,int j)  //将指定位置的元素值赋给变量
{
	int k=0;
	if (i>=t.rows || j>=t.cols)
		return false;			//失败时返回false
	while (k<t.nums && i>t.data[k].r) k++;					//查找行
	while (k<t.nums && i==t.data[k].r && j>t.data[k].c) k++;//查找列
	if (t.data[k].r==i && t.data[k].c==j)
		x=t.data[k].d;
	else
		x=0;				//在三元组中没有找到表示是零元素
	return true;			//成功时返回true
}

void DispMat(TSMatrix t)		//输出三元组
{
	int i;
	if (t.nums<=0)			//没有非零元素时返回
		return;
	printf("\t%d\t%d\t%d\n",t.rows,t.cols,t.nums);
	printf("\t------------------\n");
	for (i=0;i<t.nums;i++)
		printf("\t%d\t%d\t%d\n",t.data[i].r,t.data[i].c,t.data[i].d);
}

void TranTat(TSMatrix t,TSMatrix &tb)		//矩阵转置
{
	int p,q=0,v;					//q为tb.data的下标
	tb.rows=t.cols;tb.cols=t.rows;tb.nums=t.nums;
	if (t.nums!=0)					//当存在非零元素时执行转置
	{
		for (v=0;v<t.cols;v++)		//tb.data[q]中的记录以c域的次序排列
			for (p=0;p<t.nums;p++)	//p为t.data的下标
				if (t.data[p].c==v)
				{
					tb.data[q].r=t.data[p].c;
					tb.data[q].c=t.data[p].r;
					tb.data[q].d=t.data[p].d;
					q++;
				}
	}
}

int main()
{
	TSMatrix t,tb;
	int x,y=10;
	int A[6][7]={
		{0,0,1,0,0,0,0},
		{0,2,0,0,0,0,0},
		{3,0,0,0,0,0,0},
		{0,0,0,5,0,0,0},
		{0,0,0,0,6,0,0},
		{0,0,0,0,0,7,4}};
	CreatMat(t,A);
	printf("b:\n"); DispMat(t);
	if (Assign(t,x,2,5)==true)  //调用时返回true
		printf("Assign(t,x,2,5)=>x=%d\n",x);
	else  //调用时返回false
		printf("Assign(t,x,2,5)=>参数错误\n");
	Value(t,y,2,5);
	printf("执行Value(t,10,2,5)\n");
	if (Assign(t,x,2,5)==true)  //调用时返回true
		printf("Assign(t,x,2,5)=>x=%d\n",x);
	else  //调用时返回false
		printf("Assign(t,x,2,5)=>参数错误\n");
	printf("b:\n"); DispMat(t);
	TranTat(t,tb);
	printf("tb:\n"); DispMat(tb);
	return 1;
}

稀疏矩阵的十字链表表示

#include <stdio.h>
#include <malloc.h>
#define M 3         			//矩阵行
#define N 4           			//矩阵列
#define Max ((M)>(N)?(M):(N))   //矩阵行列较大者
typedef int ElemType;
typedef struct mtxn 
{ 
	int row;					//行号
	int col;					//列号
   	struct mtxn *right,*down;	//向右和向下的指针
	union 
	{
		ElemType value;
		struct mtxn *link;
	} tag;
} MatNode;			//十字链表类型

void CreatMat(MatNode *&mh,ElemType a[][N])	//创建a的十字链表
{
	int i,j;
	MatNode *h[Max],*p,*q,*r;
	mh=(MatNode *)malloc(sizeof(MatNode));//创建十字链表的头结点
	mh->row=M;mh->col=N;
	r=mh;					//r指向尾结点
	for (i=0;i<Max;i++)		//采用尾插法创建头结点h1,h2,…循环链表
	{
		h[i]=(MatNode *)malloc(sizeof(MatNode));
		h[i]->down=h[i]->right=h[i];		//将down和right方向置为循环的
		r->tag.link=h[i];					//将h[i]加到链表中
		r=h[i];
	}
	r->tag.link=mh;							//置为循环链表
	for (i=0;i<M;i++)						//处理每一行
	{
		for (j=0;j<N;j++)					//处理每一列
		{
			if (a[i][j]!=0)					//处理非零元素
			{
				p=(MatNode *)malloc(sizeof(MatNode));	//创建一个新结点
				p->row=i;p->col=j;p->tag.value=a[i][j];
				q=h[i];      					//查找在行表中的插入位置
                while (q->right!=h[i] && q->right->col<j) 
                  	q=q->right;
				p->right=q->right;q->right=p;	//完成行表的插入
				q=h[j];      					//查找在列表中的插入位置
				while (q->down!=h[j] && q->down->row<i) 
					q=q->down;
				p->down=q->down;q->down=p;  	//完成列表的插入
			}
		}
	}
}

void DestroyMat(MatNode *&mh)		//销毁十字链表
{
	MatNode *pre,*p,*mp;
	mp=mh->tag.link;				//mp指向h[i]
	while (mp!=mh)					//释放所有数据结点
	{
		pre=mp->right;				//pre指向h[i]的行首结点
		if (pre!=mp)				//h[i]不空
		{
			p=pre->right;			//p指向结点pre的后继结点
			while (p!=mp)
			{
				free(pre);
				pre=p; p=p->right;
			}
		}
		mp=mp->tag.link;			//mp指向下一个头结点
	}
	//释放所有的头结点
	pre=mh->tag.link;				//pre指向h[i]
	p=pre->tag.link;				//p指向h[i+1]
	while (p!=mh)
	{
		free(pre);
		pre=p; p=p->tag.link;
	}
	free(mh);
}

void DispMat(MatNode *mh)		//输出十字链表
{
	MatNode *p,*q;
	printf("行=%d  列=%d\n", mh->row,mh->col);
	p=mh->tag.link;
	while (p!=mh) 
	{	
		q=p->right;
		while (p!=q) 		//输出一行非零元素
		{
			printf("%d\t%d\t%d\n", q->row,q->col,q->tag.value);
			q=q->right;
		}
		p=p->tag.link;
	}
}

//本主程序用于调试
int main()
{
	ElemType a[M][N]={{1,0,0,2},{0,0,3,0},{0,0,0,4}};
	MatNode *mx;
	CreatMat(mx,a);
	printf("a的十字链表:\n");DispMat(mx);
	DestroyMat(mx);
	return 1;
}

广义表基本运算算法

#include <stdio.h>
#include <malloc.h>
typedef char ElemType;
typedef struct lnode
{
	int tag;					//结点类型标识
	union 
	{
		ElemType data;			//原子值
		struct lnode *sublist;	//指向子表的指针
	} val;
	struct lnode *link;			//指向下一个元素
} GLNode;

int GLLength(GLNode *g)			//求广义表g的长度
{
	int n=0;
	GLNode *g1;
	g1=g->val.sublist;			//g指向广义表的第一个元素
	while (g1!=NULL)
	{	
		n++;					//累加元素个数
		g1=g1->link;
	}
	return n;
}

int GLDepth(GLNode *g)			//求广义表g的深度
{
	GLNode *g1;
	int maxd=0,dep;
	if (g->tag==0)				//为原子时返回0
		return 0;
	g1=g->val.sublist;			//g1指向第一个元素
	if (g1==NULL)				//为空表时返回1
		return 1;
	while (g1!=NULL)			//遍历表中的每一个元素
	{	
		if (g1->tag==1)			//元素为子表的情况
		{
			dep=GLDepth(g1);	//递归调用求出子表的深度
			if (dep>maxd)		//maxd为同一层所求过的子表中深度的最大值
				maxd=dep;
		}
		g1=g1->link;			//使g1指向下一个元素
	}
	return(maxd+1);				//返回表的深度
}

GLNode *CreateGL(char *&s)				//创建由括号表示法表示s的广义表链式存储结构
{
	GLNode *g;
	char ch=*s++;						//取一个字符
	if (ch!='\0')						//串未结束判断
	{
		g=(GLNode *)malloc(sizeof(GLNode));//创建一个新结点
		if (ch=='(')					//当前字符为左括号时
		{
			g->tag=1;					//新结点作为表头结点
			g->val.sublist=CreateGL(s); //递归构造子表并链到表头结点
		}
		else if (ch==')') 
			g=NULL;           			//遇到')'字符,g置为空
		else if (ch=='#')				//遇到'#'字符,表示为空表
			g=NULL;
		else							//为原子字符
		{
			g->tag=0;					//新结点作为原子结点
			g->val.data=ch;
		}
	}
	else								//串结束,g置为空
		g=NULL;
	ch=*s++;                           	//取下一个字符
	if (g!=NULL)                      	//串未结束,继续构造兄递结点
		if (ch==',')                  	//当前字符为','
			g->link=CreateGL(s);   		//递归构造兄递结点
		else                            //没有兄弟了,将兄弟指针置为NULL
			g->link=NULL;
	return g;                     		//返回广义表g
}

void DestroyGL(GLNode *&g)		//销毁广义表
{
	GLNode *g1,*g2;
	g1=g->val.sublist;			//g1指向广义表的第一个元素
	while (g1!=NULL)			//遍历所有元素
	{
		if (g1->tag==0)			//若为原子结点
		{	g2=g1->link;		//g2临时保存兄弟结点
			free(g1);			//释放g1所指原子结点
			g1=g2;				//g1指向后继兄弟结点
		}
		else					//若为子表
		{	g2=g1->link;		//g2临时保存兄弟结点
			DestroyGL(g1);		//递归释放g1所指子表的空间
			g1=g2;				//g1指向后继兄弟结点
		}
	}
	free(g);					//释放头结点空间
}

void DispGL(GLNode *g)					//输出广义表g
{
	if (g!=NULL)                 		//表不为空判断
	{									//先处理g的元素
		if (g->tag==0)               	//g的元素为原子时
			printf("%c", g->val.data);  //输出原子值
		else							//g的元素为子表时
		{
			printf("(");                //输出'('
			if (g->val.sublist==NULL)  	//为空表时
				printf("#");
			else						//为非空子表时
				DispGL(g->val.sublist); //递归输出子表
			printf(")");               	//输出')'
		}
		if (g->link!=NULL) 
		{
			printf(",");
			DispGL(g->link);            //递归输出后续表的内容
		}
	}
}

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据结构教程》是李春葆撰写的一本经典教材,这里提到的第三是其更新后的本。这本教材是计算机科学和软件工程专业的学生必备的参考书之一。 这本教程数据结构作为核心内容,系统而全面地介绍了各种数据结构及其应用。其中包括线性表、栈、队列、树、图等常见的数据结构以及它们的操作和实现方式。每个章节都有详细而清晰的讲解,配有大量的示例和习题,有助于读者理解和掌握各种数据结构的基本知识和算。 教材的第三相比前两进行了全面的更新和改进。在保留经典内容的基础上,增加了一些新的数据结构和算的讲解,如红黑树、哈希表、最短路径算等。并且,教材还增加了一些实际应用的案例分析,如文件系统、数据库管理系统等,让读者更好地理解数据结构在实际应用中的作用和意义。 这本教程深入浅出,适合初学者和有一定编程基础的读者阅读。它不仅给出了数据结构的原理和概念,更重要的是通过丰富的例子和习题培养了读者的实际操作和问题解决能力。同时,教材还提供了配套的源代码和实验指导,供读者进一步学习和实践。 总之,《数据结构教程李春葆第三是一本值得推荐的编程教材。无论是学生还是从事计算机相关工作的专业人士,阅读并掌握其中的知识都将对他们的编程能力和问题解决能力有所提升。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值