《数据结构(A)》第5章作业设计型作业

1   设计型题目

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

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

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

2  设计型题目解答

【5.1题解答】:

算法设计思路:

  1. 遍历数组中的左右行,找出该行的最小值,然后和该列上的元素进行比较,观察是否为列上的最大值
  2. 如果有多个鞍点,分别存储在数组里,以此输出
  3. 如果没有鞍点,输出“没有鞍点”。

 源代码:

main.cpp

#include <iostream>
#include "Chapter 5_1.h"
//结构体声明

/*
*函数功能:实现矩阵鞍点求解
*/
int main()
{
  prepare();//输入矩阵
  work();//判断该矩阵上是否有鞍点
  printans();//打印输出鞍点
  return 0;
}

Chapter 5_1.h

#pragma once
#include <iostream>
using namespace std;
typedef struct node
{
  int x, y;
}anstype;

//函数声明
void prepare();//输入一个矩阵
void work();
void printans();//将获取到的鞍点信息打印输出
int check(int x, int y);
void remember(int x, int y);//存储输入的矩阵的值

Chapter 5_1.cpp

#include "Chapter 5_1.h"
#include <iostream>
using namespace std;
//变量声明
int matrix[1000][1000];
anstype ans[1000];
int lenx = 0, leny = -1;

void prepare()
{
  //声明局部变量
  char tem;        //用于接收用户输入的矩阵数值字符
  int Intem = -1;  //存放用户输入矩阵的最大的列数

  //初始化全局变量
  lenx = 0;
  ans[0].x = 0;

  printf("输入一个矩阵:\n");

  while (1)
  {
	//开启新的一行输入时,将列标重置为0
	leny = 0;

	while (1)
	{
	  //如果用户输入空格,就空循环,直到用户输入非空格的字符
	  while (tem = getchar(), tem == ' ') {};

	  if ((tem == '\n') || (tem == EOF))
	  {
		//用户输入回车或EOF时结束对矩阵一行数据的输入
		break;
	  }

	  //将用户输入的字符转换为数值存入matrix数组
	  matrix[lenx][leny] = tem - '0';

	  //将列标指向下一列
	  leny = leny + 1;
	}

	if (leny > Intem)
	{
	  //将最大列号存入Intem变量
	  Intem = leny;
	}

	if (tem == EOF)
	{
	  //如果用户输入EOF,则退出循环
	  break;
	}

	//将行标加1,开启下一行的数据输入
	lenx = lenx + 1;
  }

  //将最大行号写回leny变量,后续函数需要用到
  leny = Intem;
}

int check(int x, int y)
{
  int i;

  for (i = 0; i < lenx; i = i + 1) {
	if (matrix[i][y] < matrix[x][y]) return 0;
  }

  return 1;
}

void remember(int x, int y)
{
  ans[0].x = ans[0].x + 1;
  ans[ans[0].x].x = x;
  ans[ans[0].x].y = y;
}


void work()
{
  int i, j;
  int tem;
  int ColIndex[100] = { 0 };

  for (i = 0; i < lenx; i = i + 1)
  {
	tem = 0;
	for (j = 1; j < leny; j = j + 1)
	  if (matrix[i][j] > matrix[i][tem])
		tem = j;
	for (j = 0; j < leny; j = j + 1)
	{
	  if (matrix[i][j] == matrix[i][tem])
	  {
		ColIndex[0] = ColIndex[0] + 1;
		ColIndex[ColIndex[0]] = j;
	  }
	}
	for (j = 1; j <= ColIndex[0]; j = j + 1)
	{
	  if (check(i, ColIndex[j]) == 1) remember(i, ColIndex[j]);
	}
  }
}

/*
*函数功能:将获取到的鞍点信息打印输出
*/
void printans()
{
  if (ans[0].x == 0)
  {
	printf("没有鞍点\n");
	return;
  }

  int i;

  for (i = 1; i <= ans[0].x; i = i + 1)
  {
	printf("第%d个鞍点是(%d,%d)\n", i, ans[i].x + 1, ans[i].y + 1);
  }
}

运行结果截图:

 

【5.2题解答】:

算法设计思路:

  1. 输入三元组的思路:逐个输入、逐个存入。
  2. 转置的思路:普通转置法做双重遍历,查找满足第i列的所有元素,然后存在三元组中。  
  3. 快速转置法,将每一列的非零元个数存在num[i]中,每一列的开始元素存在cpot[i]中。

源代码:

main.cpp

#include "Chapter 5_2.h"
int main() {
  TSMatrix T, S,M;
  InitSparseMatrix(T);//初始化三元组
  TraverseSparseMatrix(T);//打印输出三元组
  Transmat(T,S);//一般转置法转置三元组
  printf("一般转置法:\n");
  TraverseSparseMatrix(S);//将转置后的三元组打印输出
  FastTransmat(T,M);//快速转置法转置三元组
  printf("快速转置法:\n");
  TraverseSparseMatrix(M);//将转置后的三元组打印输出
}

Chapter 5_2.h

#pragma once
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <iostream>
using namespace std;
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define MAXSIZE 100 //三元组的最大存储结构
typedef int Status;
typedef int Elemtype;
typedef struct {
  int i, j;
  Elemtype e;
}Triple;//三元组的非零元信息

typedef struct {
  Triple data[MAXSIZE + 1];
  int mu, nu, tu;//矩阵的行数、列数、非零元个数
}TSMatrix;

Status  InitSparseMatrix(TSMatrix& T);//初始化三元组
Status TraverseSparseMatrix(TSMatrix T);//矩阵打印输出
Status Transmat(TSMatrix M, TSMatrix& N);//矩阵的转置
Status FastTransmat(TSMatrix M, TSMatrix& N);//矩阵的快速转置

Chapter 5_2.cpp

#include "Chapter 5_2.h"
Status  InitSparseMatrix(TSMatrix& T) {
  int m, n, t;
  printf("请输入总行数、列数、非零元个数\n");
  scanf_s("%d %d %d\n", &m, &n, &t);
  T.mu = m; T.nu = n; T.tu = t;
  //T.tu = 0;
  printf("请依次输入三元组的行数、列数、值\n");
  for (int i = 1; i <= t; i++) {
    int row, col, elem;
    scanf_s("%d %d %d ", &row, &col, &elem);
    T.data[i].i = row;
    T.data[i].j = col;
    T.data[i].e = elem;
    //T.tu++;
  }
  return OK;
}

Status TraverseSparseMatrix(TSMatrix T) {
  printf("三元组的信息为:\n");
  printf("%d %d %d\n", T.mu, T.nu, T.tu);
  for (int i = 1; i <=T.tu; i++) {
    printf("%d %d %d\n ", T.data[i].i, T.data[i].j, T.data[i].e);
  }
  return OK;
}

Status Transmat(TSMatrix M, TSMatrix& N) {
  N.mu = M.nu; N.nu = M.mu; N.tu = M.tu;
  if (M.tu != 0) {
    int q = 1;
    for (int col = 1; col <= M.nu; col++) {//按M的列转
      for (int p = 1; p <= M.tu; p++) {// 对M三元组表扫描一遍
        if (M.data[p].j == col) {
          N.data[q].i = M.data[p].j;
          N.data[q].j = M.data[p].i;
          N.data[q].e = M.data[p].e;
          q++;//q为N三元组表中的行号
        }
      }
    }
  }
  //TraverseSparseMatrix(T)
  return OK;
}

Status FastTransmat(TSMatrix M, TSMatrix& N) {
  N.mu = M.nu; N.nu = M.mu; N.tu = M.tu;
  //int t = M.nu;
  int num[100];
  int cpot[100];
  int col, t, p, q;
  if (M.tu != 0) {
    for (col = 1; col <= M.nu; col++)
      num[col] = 0;//初始化num向量
    for (t = 1; t <= M.tu; t++)
      num[M.data[t].j]++;//求M中每一列含非零元个数
    cpot[1] = 1;
    for (col = 2; col <= M.nu; col++)
      //求M中每一列的第一个非零元在B.data中的序号(位置)
      cpot[col] = cpot[col - 1] + num[col - 1];
    for (p = 1; p <= M.tu; p++) {
      col = M.data[p].j;
      q = cpot[col];
      N.data[q].i = M.data[p].j;//p为M中的行号
      N.data[q].j = M.data[p].i;//q为转置后在N中的行号
      N.data[q].e = M.data[p].e;
      cpot[col]++;
    } 
    
  }
 return OK;
}

运行结果截图:

 【5.3题解答】:

main.cpp

#include "Chapter 5_3.h"
void visit(AtomType e)
{
  printf("%c ", e);
}

void main()
{
  char p[80];
  GList l, m;
  HString t;
  InitString(&t);
  InitGList(&l);
  InitGList(&m);
  printf("空广义表l的深度=%d l是否空?%d(1:是 0:否)\n", GListDepth(l), GListEmpty(l));
  printf("请输入广义表l(书写形式:空表:(),单原子:a,其它:(a,(b),b)):\n");
  gets(p);
  StrAssign(&t, p);
  CreateGList(&l, t);
  printf("广义表l的长度=%d\n", GListLength(l));
  printf("广义表l的深度=%d l是否空?%d(1:是 0:否)\n", GListDepth(l), GListEmpty(l));
  printf("遍历广义表l:\n");
  Traverse_GL(l, visit);
  printf("\n复制广义表m=l\n");
  CopyGList(&m, l);
  printf("广义表m的长度=%d\n", GListLength(m));
  printf("广义表m的深度=%d\n", GListDepth(m));
  printf("遍历广义表m:\n");
  Traverse_GL(m, visit);
  DestroyGList(&m);
  m = GetHead(l);
  printf("\nm是l的表头,遍历广义表m:\n");
  Traverse_GL(m, visit);
  DestroyGList(&m);
  m = GetTail(l);
  printf("\nm是l的表尾,遍历广义表m:\n");
  Traverse_GL(m, visit);
  InsertFirst_GL(&m, l);
  printf("\n插入l为m的表头,遍历广义表m:\n");
  Traverse_GL(m, visit);
  printf("\n删除m的表头,遍历广义表m:\n");
  DestroyGList(&l);
  DeleteFirst_GL(&m, &l);
  Traverse_GL(m, visit);
  printf("\n");
  DestroyGList(&m);
}

Chapter 5_3.h

#pragma once
typedef int Status;
typedef int Boolean; 

#include<malloc.h>
#include<process.h> 
#include<stdio.h> 
#include<limits.h> 
/* 函数结果状态代码 */
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2 

typedef char AtomType; /* 定义原子类型为字符型 */
typedef enum { ATOM, LIST }ElemTag; 
typedef struct GLNode
{
  ElemTag tag; /* 公共部分,用于区分原子结点和表结点 */
  union /* 原子结点和表结点的联合部分 */
  {
	AtomType atom; /* atom是原子结点的值域,AtomType由用户定义 */
	struct
	{
	  struct GLNode* hp, * tp;
	}ptr; /* ptr是表结点的指针域,prt.hp和ptr.tp分别指向表头和表尾 */
  }a;
}*GList, GLNode; /* 广义表类型 */

Chapter 5_3.cpp

#include "Chapter 5_3.h"
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
	{
	  CopyGList(&((*T)->a.ptr.hp), L->a.ptr.hp);
	  /* 复制广义表L->ptr.hp的一个副本T->ptr.hp */
	  CopyGList(&((*T)->a.ptr.tp), L->a.ptr.tp);
	  /* 复制广义表L->ptr.tp的一个副本T->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; 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);
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值