数据结构实验3--数组与广义表

本系列文章广泛借鉴了各种教材和博客文章,由于完成时间比较久远,如果有遗漏标注的请联系我补充或删除解答。本文中解答仅供参考学习。

其他章节实验见:分类 - 数据结构 - Loststar’s blog

鞍点问题

题目

若矩阵A中的某一元素A[i,j]是第i行中的最小值,而又是第j列中的最大值,则称A[i,j]是矩阵A中的一个鞍点。写出一个可以确定鞍点位置的程序。

解答

#include<stdio.h>
#define m 3
#define n 3
int arr[m][n] = { //矩阵
	30,40,11,
	2,5,6,
	1,8,9
};
int main()
{
	for (int i = 0; i < m; i++)
	{
		int dstI = i, dstJ = 0;
		int minX = arr[i][0];
		
		//找第i行的最小值(dstX,dstY)
		for (int j = 0; j < n; j++)
		{
			if (arr[i][j] < minX) 
			{
				minX = arr[i][j];
				dstI = i;
				dstJ = j;
			}
		}

		int maxY = arr[dstI][dstJ],flag=1;

		//遍历dstJ列,查找有没有比arr[dstI][dstJ]大的数
		for (int j = 0; j < m; j++)
		{
			if (arr[j][dstJ] > maxY)
			{
				flag = 0;
				break;
			}
		}
		
		if (flag == 1)
		{
			flag = 0;
			printf("(%d,%d)", dstI, dstJ);
		}
	}
}

运行结果

得到鞍点。在上文提到的测试矩阵中是(0,2)

稀疏矩阵转置

题目

输入稀疏矩阵中每个元素的行号、列号、值,建立稀疏矩阵的三元组存储结构,并将此矩阵转置,显示转置前后的三元组结构。

解答

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#define  MAXSIZE  12500
typedef struct {
	int  i, j;      //该非零元的行下标和列下标
	int value;    // 该非零元的值
} Triple;  // 三元组类型
typedef struct {
	Triple data[MAXSIZE + 1];
	int iTot;
	int jTot;
	int	numTot; //行数,列数,非零元个数
} TSMatrix;  // 稀疏矩阵类型

int TransposeSMatrix(TSMatrix M, TSMatrix &T)
{
	T.iTot = M.jTot;
	T.jTot = M.iTot;
	T.numTot = M.numTot;
	int q = 1;
	if (T.numTot!=0)
	{
		for (int col = 1; col <= M.jTot; col++)
		{
			for (int p = 1; p <= M.numTot; p++)
			{
				if (M.data[p].j == col)
				{
					T.data[q].i = M.data[p].j;
					T.data[q].j = M.data[p].i;
					T.data[q].value = M.data[p].value;
					q++;
				}
			}
		}
	}
	return 0;
}
int ShowSMatrix(TSMatrix M)
{
	int p = 1;
	for (int i = 1; i <= M.iTot; i++)
	{
		for (int j = 1; j <= M.jTot; j++)
		{
			if (M.data[p].i == i && M.data[p].j == j)
			{
				printf("%d ", M.data[p].value);
				p++;
			}
			else
			{
				printf("0 ");
			}
		}
		printf("\n");
	}
	return 0;
}
int main()
{
	TSMatrix M, T;
	int a, b, c;
	printf("行数、列数、非零元个数:\n");
	scanf("%d %d %d", &M.iTot, &M.jTot, &M.numTot);
	for (int temp = 1; temp <= M.numTot; temp++)
	{
		scanf("%d %d %d", &M.data[temp].i, &M.data[temp].j, &M.data[temp].value);
	}
	printf("转置前\n");
	ShowSMatrix(M);
	TransposeSMatrix(M, T);
	printf("转置后\n");
	ShowSMatrix(T);
}

运行结果

广义表

题目

用头尾链表存储表示法建立广义表,输出广义表,求广义表的表头、广义表的表尾和广义表的深度。

解答

这题我当时不会,大部分对着博客(广义表的创建 喜爱兰兰-CSDN博客 创建广义表)学然后默写调通。现在把默写部分替换回原作者带有清晰注释的部分。求深度部分来自严蔚敏《数据结构》。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_STR_LEN 100
typedef char AtomType;
typedef enum { ATOM, LIST } ElemTag;
// ATOM==0:原子, LIST==1:子表
typedef struct GLNode {
	ElemTag  tag;   // 标志域
	union {
		AtomType  atom;      // 原子结点的数据域
		struct { struct GLNode *hp, *tp; } ptr;
	};
} *GList;

char hstr[MAX_STR_LEN], istr[MAX_STR_LEN];

void SubString(char *substr, char *inputstr, int start, int end) 
{	//截取字符串中间内容,本程序中主要用于去头尾括号
	for (char *temp = inputstr + start; temp <= inputstr + end; temp++)
	{
		*substr = *temp;
		*substr++;
	}
	*substr = '\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));

	if (i < n) {
		SubString(headstr, inputstr, 0, i - 1);
		SubString(inputstr, inputstr, i + 1, strlen(inputstr) - 1);
	}
	else {
		strcpy(headstr, inputstr);
		inputstr = '\0'; 
	}
}
int CreateGList(GList &L, char *s)
{
	if (strcmp(s, "()") == 0)
		L = NULL; //建立空表
	else {
		L = (GList)malloc(sizeof(struct GLNode));  //新建一个表结点 
		if (L == NULL)
			return -1;
		if (strlen(s) == 1) { //原子结点 
			L->tag = ATOM;;
			L->atom = *s;
		}
		else {
			char *headstr = hstr;
			L->tag = LIST;
			SubString(s, s, 1, strlen(s) - 2); //脱去最外边的括号 
			GList pointer = L;
			do { //创建子表 
				SplitHeadStr(s, headstr); //headstr为分割后的表头,s为分割后的表尾 
				char tstr[MAX_STR_LEN];
				strcpy(tstr, headstr);
				CreateGList(pointer->ptr.hp, tstr);  //递归创建表头 
				if (s != NULL && strlen(s) != 0) {  //如果表尾不为空的话 
					GList tailnode = (GList)malloc(sizeof(struct GLNode));
					if (pointer == NULL)
						return -1;
					tailnode->tag = LIST;  //广义表的表尾肯定是一张表 
					pointer->ptr.tp = tailnode;
					pointer = tailnode; 
				} 
			} while (s != NULL && strlen(s) != 0);  //直到表尾为空NULL则退出 
			pointer->ptr.tp = NULL;  //最后将表尾赋值为NULL 
		} 
	}
	return 0;
}

void PrintGList(const GList L) {
	printf("(");
	GList pointer = L;  
	do {
		GList temp = pointer->ptr.hp;
		if (temp != NULL) {  //递归输出表头中原子结点 
			if (temp->tag == ATOM)
			{
				printf("%c", temp->atom);
			}
			else
			{
				PrintGList(temp);
			}
				
		}
		if (pointer->ptr.tp != NULL)
		{	//后面还有
			printf(",");
		}
		pointer = pointer->ptr.tp;  // 指针指向表尾,判断表尾是否空
	} while (pointer != NULL);
	printf(")");
}

int GetGListDepth(GList L)
{
	if (!L)
		return 1;//空表
	if (L->tag == ATOM)
		return 0;//原子
	int max = 0;
	for (GList pp = L; pp; pp = pp->ptr.tp) 
	{
		int dep = GetGListDepth(pp->ptr.hp);
		if (dep > max) {
			max = dep;//每次找到表中遍历到深度最大的表,并用max记录
		}
	}
	return max + 1;
}

int main() {
	char s[100];
	scanf("%s", &s);
	int left = 0, right = 0;
	for (int i = 0; i < strlen(s); i++)
	{
		if (s[i] == '(')
			left++;
		if (s[i] == ')')
			right++;
	}
	if (left != right)
	{
		printf("error");
		return -1;
	}
	strcpy(istr, s);
	GList L;
	char *head=(char*)malloc(MAX_STR_LEN*sizeof(char)), *tail=(char*)malloc(MAX_STR_LEN * sizeof(char));
	strcpy(tail, istr);
	CreateGList(L, istr);
	SubString(tail, tail, 1, strlen(tail) - 2);
	printf("广义表:");
	PrintGList(L);
	SplitHeadStr(tail, head);
	printf("\nhead:%s\ntail:%s\n",head,tail);
	printf("\n深度:%d", GetGListDepth(L));
	return 0;
}

结果


数据结构实验3--数组与广义表
https://blog.loststar.tech/posts/5a6e9197/
作者
loststar
发布于
2021年3月23日
许可协议