1、实现稀疏矩阵的基本运算
#include <stdio.h>
#include <stdbool.h>
#define N 4
#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; // 三元组顺序表定义
//产生稀疏矩阵A的三元组表示t
void create_matrix(TSMatrix &t,ElemType A[N][N])
{
int i,j;
t.rows=N;
t.cols=N;
t.nums=0; //非零元素个数
for (i = 0; i < N; 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++; //非零元素个数增1
}
}
}
}
//输出三元组表示t
void disp_matrix(TSMatrix t)
{
int i;
if (t.nums<=0)
return;
printf(" %d %d %d
", t.rows, t.cols, t.nums); //行数,列数,非零元素个数
printf(" ------------------
");
for (i = 0; i < t.nums; i++)
{
printf(" %d %d %d
", t.data[i].r, t.data[i].c, t.data[i].d);
}
}
//求三元组表示t的转置矩阵T
void tran_matrix(TSMatrix t,TSMatrix &T)
{
int p,v;
int q=0; //q为T.data的下标
T.rows=t.cols;
T.cols=t.rows;
T.nums=t.nums;
if(t.nums!=0)
{
for(v=0;v<t.cols;v++) //T.data[q]中的记录以c域的次序排列
{
for(p=0;p<t.nums;p++) //p为t.data的下标
{
if (t.data[p].c==v)
{
T.data[q].r=t.data[p].c; //转置矩阵的行号
T.data[q].c=t.data[p].r; //转置矩阵的列号
T.data[q].d=t.data[p].d; //转置矩阵的元素值
q++;
}
}
}
}
}
//求c=a+b
bool matrix_add(TSMatrix a, TSMatrix b, TSMatrix &c)
{
int i = 0; //a中非零元素个数索引
int j = 0; //b中非零元素个数索引
int k = 0; //c中非零元素个数
ElemType v;
if(a.rows!=b.rows||a.cols!=b.cols) //这样不能相加
return false;
//c的行列数与a的相同
c.rows=a.rows;
c.cols=a.cols;
while(i<a.nums&&j<b.nums)
{
if(a.data[i].r==b.data[j].r) //a元素的行号等于b元素的行号
{
if(a.data[i].c<b.data[j].c) //a元素的列号小于b元素的列号
{
//将a中元素加到c
c.data[k].r=a.data[i].r;
c.data[k].c=a.data[i].c;
c.data[k].d=a.data[i].d;
k++;
i++;
}
else if(a.data[i].c>b.data[j].c) //a元素的列号大于b元素的列号
{
//将b中元素加到c
c.data[k].r = b.data[j].r;
c.data[k].c = b.data[j].c;
c.data[k].d = b.data[j].d;
k++;
j++;
}
else //a元素的列号等于b元素的列号
{
v = a.data[i].d + b.data[j].d;
if(v != 0) //只将不为0的结果添加到c中
{
c.data[k].r = a.data[i].r;
c.data[k].c = a.data[i].c;
c.data[k].d = v;
k++;
}
i++;
j++;
}
}
else if(a.data[i].r < b.data[j].r) //a元素的行号小于b元素的行号
{
//将a中元素加到c
c.data[k].r = a.data[i].r;
c.data[k].c = a.data[i].c;
c.data[k].d = a.data[i].d;
k++;
i++;
}
else //a元素的行号大于b元素的行号
{
//将b中元素加到c
c.data[k].r = b.data[j].r;
c.data[k].c = b.data[j].c;
c.data[k].d = b.data[j].d;
k++;
j++;
}
c.nums=k;
}
return true;
}
//获取三元组t表示的A[i][j]值
int get_value(TSMatrix t,int i,int j)
{
int k=0;
while(k<t.nums&&(t.data[k].r!=i||t.data[k].c!=j))
k++;
if(k<t.nums)
return t.data[k].d;
else
return 0;
}
//求c=a*b
bool matrix_mul(TSMatrix a,TSMatrix b,TSMatrix &c)
{
int i;
int j;
int k;
int p = 0; // 矩阵c的非零元素个数
ElemType s;
if(a.cols != b.rows) //a的列数不等于b的行数时不能进行乘法运算
return false;
for(i=0;i<a.rows;i++) //矩阵c的行数
{
for(j=0;j<b.cols;j++) //矩阵c的列数
{
s=0;
for(k=0;k<a.cols;k++)
{
s=s+get_value(a,i,k)*get_value(b,k,j); //求三元组元素
}
if(s!=0)
{
c.data[p].r = i; //三元组元素的行号
c.data[p].c = j; //三元组元素的列号
c.data[p].d = s; //三元组元素的元素值
p++;
}
}
}
c.rows = a.rows;
c.cols = b.cols;
c.nums = p; // 矩阵c的非零元素个数
return true;
}
int main()
{
ElemType a1[N][N] = {
{1, 0, 3, 0},
{0, 1, 0, 0},
{0, 0, 1, 0},
{0, 0, 1, 1}
};
ElemType b1[N][N] = {
{3, 0, 0, 0},
{0, 4, 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 2}
};
TSMatrix a, b, c;
create_matrix(a, a1);
create_matrix(b, b1);
printf("a的三元组:
");
disp_matrix(a);
printf("b的三元组:
");
disp_matrix(b);
printf("a转置为c
");
tran_matrix(a, c);
printf("c的三元组:
");
disp_matrix(c);
printf("c=a+b
");
matrix_add(a, b, c);
printf("c的三元组:
");
disp_matrix(c);
printf("c=a*b
");
matrix_mul(a, b, c);
printf("c的三元组:
");
disp_matrix(c);
}
2、实现广义表的基本运算
#include <stdio.h>
#include <malloc.h>
typedef struct lnode
{
int tag; //结点类型标识,tag为公共部分,只能为1和0,1代表表结点,0代表原子结点
union
{
char data; //原子结点的值域
struct lnode *sublist; //表结点的表头的表头指针
}val;
struct lnode *link; // 指向下一个元素
}GLNode; // 声明广义表结点类型
//返回由括号表示法表示s的广义表链式存储结构(递归方法),字符串变广义表
GLNode *create_gl(char *&s)
{
GLNode *g;
char ch = *s++; // 取一个字符
if(ch != ' ') // 串未结束判断
{
g = (GLNode *)malloc(sizeof(GLNode)); // 创建一个新结点
if(ch == '(') // 当前字符为左括号时
{
g->tag = 1; // 新结点作为表头结点
g->val.sublist = create_gl(s); // 递归构造子表并链到表头结点
}
else if(ch == ')') // 遇到右括号字符,g设置为空
{
g = NULL;
}
else if(ch == '#') // 遇到#字符,表示空表
{
g->val.sublist = NULL;
}
else // 为原子字符
{
g->tag = 0; // 新结点作为原子结点
g->val.data = ch;
}
}
else // 串结束,g设置为空
{
g = NULL;
}
ch = *s++; // 取下一个字符
if(g != NULL) // 串未结束,继续构造兄弟结点
{
if(ch == ',') // 当前字符为逗号
{
g->link = create_gl(s); // 递归构造兄弟结点
}
else // 没有兄弟了,将兄弟指针设置为NULL
{
g->link = NULL;
}
}
return g; // 返回广义表g
}
//输出广义表g
void disp_gl(GLNode *g)
{
if(g != NULL) // 表非空判断
{
if(g->tag == 0) // g的元素为原子时
printf("%c", g->val.data); // 输出原子值
else // g的元素为子表时
{
printf("(");
if(g->val.sublist == NULL) // 为空表时
printf("#");
else // 为非空子表时
disp_gl(g->val.sublist); // 递归输出子表
printf(")");
}
if(g->link != NULL)
{
printf(",");
disp_gl(g->link); // 递归输出g的兄弟
}
}
}
//求广义表g的长度
int gl_length(GLNode *g)
{
int n = 0;
g = g->val.sublist; // g指向广义表的第一个元素
while(g != NULL)
{
n++;
g = g->link;
}
return n;
}
//求广义表g的深度
int gl_depth(GLNode *g)
{
int max_dep = 0;
int dep;
if(g->tag == 0)
return 0;
g = g->val.sublist; // g指向第一个元素
if(g == NULL) // 为空表时返回1
return 1;
while(g != NULL) // 遍历表中的每一个元素
{
if(g->tag == 1) // 元素为子表的情况
{
dep = gl_depth(g); // 递归调用求出子表的深度
if(dep > max_dep)
max_dep = dep; // max_dep为同一层所求过的子表中深度的最大值
}
g = g->link; // g指向下一个元素
}
return (max_dep + 1); // 返回表的深度
}
//求广义表g的最大原子
char gl_max_atom(GLNode *g)
{
char max1, max2;
if(g != NULL)
{
if(g->tag == 0)
{
max1 = gl_max_atom(g->link);
return (g->val.data > max1 ? g->val.data : max1);
}
else
{
max1 = gl_max_atom(g->val.sublist);
max2 = gl_max_atom(g->link);
return (max1 > max2 ? max1 : max2);
}
}
else
return 0;
}
//销毁广义表g
void destroy_gl(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临时保存兄弟结点
destroy_gl(g1); // 递归释放g1所指子表的空间
g1 = g2; // g1指向后继兄弟结点
}
}
free(g); // 释放头结点空间
}
int main()
{
GLNode *g;
char *str = "(b,(b,a,(#),d),((a,b),c,((#))))";
g = create_gl(str);
printf("广义表g:");
disp_gl(g);
printf("
");
printf("广义表g的长度:%d
", gl_length(g));
printf("广义表g的深度:%d
", gl_depth(g));
printf("广义表g的最大原子:%c
", gl_max_atom(g));
destroy_gl(g);
}
3、求5×5阶螺旋矩阵
#include <stdio.h>
#define MAX_LEN 10
/**
* 学习于CSDN作者-静能生悟
* 螺旋方阵:
* 是指对任意给定的N,将1到N×N的数字从左上角第1个格子开始,
* 按顺时针螺旋方向顺序填入N×N的方阵里。
* 以N=5为例
* 1 2 3 4 5
* 16 17 18 19 6
* 15 24 25 20 7
* 14 23 22 21 8
* 13 12 11 10 9
* 算法思路:
* 以前做Java题遇见过,主要在于如何表达一圈上的数字,最简单用二阶模拟。
* 用二维数组a存放n阶螺旋方阵。偶数阶螺旋方阵共有m(m=n/2)圈,
* 奇数阶螺旋方阵共有m(m=[n/2]+1)圈,对于第i(i从0到m-1共执行m次)圈
* 循环,产生该圈上横行的数字,产生该圈右竖行的数字,产生该圈下
* 横行的数字,产生该圈左竖行的数字。最后输出该方阵。
*/
void helix_matrix(int a[MAX_LEN][MAX_LEN], int n)
{
int m; // 圈数
int i;
int j;
int k = 0;
if(n % 2 == 0) //偶数阶螺旋方阵
m = n / 2;
else //奇数阶螺旋方阵
m = n / 2 + 1;
for(i = 0; i < m; i++)
{
//产生该圈上横行的数字
for(j = i; j < n - i; j++)
{
k++;
a[i][j] = k;
}
//产生该圈右竖行的数字
for(j = i + 1; j < n - i; j++)
{
k++;
a[j][n - i - 1] = k;
}
//产生该圈下横行的数字
for(j = n - i - 2; j >= i; j--)
{
k++;
a[n - i - 1][j] = k;
}
//产生该圈左竖行的数字
for(j = n - i - 2; j >= i + 1; j--)
{
k++;
a[j][i] = k;
}
}
}
int main()
{
int n, i, j;
int a[MAX_LEN][MAX_LEN];
printf("输入n(n<10):");
scanf("%d", &n);
helix_matrix(a, n);
printf("%d阶数字方阵如下:
", n);
for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++)
{
printf("%4d", a[i][j]);
}
printf("
");
}
}
4、求一个矩阵的马鞍点
#include <stdio.h>
#include <stdbool.h>
#define M 3
#define N 3
/**
* 马鞍点:行中最小元素,列中最大元素
* 算法思路:
* 先求出每行的最小值元素,放入数组min[M]中,再求出每列的最大值元素,放入数组max[N]中,
* 若某元素既在min[i]中,又在max[j]中,则该元素A[i][j]是马鞍点,找出所有这样的元素,也就找
* 到了所有马鞍点。
*/
void min_max(int A[M][N])
{
int i, j;
bool have = false;
int min_row[M], max_col[N];
//每行的最小值元素放入min_row[0,1,...,M-1]中
for(i = 0; i < M; i++)
{
min_row[i] = A[i][0]; //假设第i行第0列的元素为第i行的最小值元素
for(j = 1; j < N; j++)
{
if(A[i][j] < min_row[i])
{
min_row[i] = A[i][j];
}
}
}
//每列的最大值元素,放入max_col[0,1,...,N-1]中
for(j = 0; j < N; j++)
{
max_col[j] = A[0][j]; //假设第0行第j列的元素为第j列的最大值元素
for(i = 1; i < M; i++)
{
if(A[i][j] > max_col[j])
{
max_col[j] = A[i][j];
}
}
}
//判断是否为马鞍点
for(i = 0; i < M; i++)
{
for(j = 0; j < N; j++)
{
if(min_row[i] == max_col[j])
{
printf(" A[%d][%d] = %d
", i, j, A[i][j]);
have = true;
}
}
}
if(!have)
printf("没有马鞍点
");
}
int main()
{
int i, j;
//定义二维数组并初始化
int A[M][N] = {
{9, 7 , 6},
{20, 26, 22},
{28, 36, 25}
};
//打印A
printf("A矩阵:
");
for(i = 0; i < M; i++)
{
for(j = 0; j < N; j++)
printf("%4d", A[i][j]);
printf("
");
}
//打印马鞍点
printf("A矩阵中的马鞍点:
");
min_max(A);
}
5、求两个对称矩阵之和与乘积
#include <stdio.h>
#define N 4
#define M 10 // 4*4/2+2
/**
* 对称矩阵M的第i行和第j列的元素的数据存储在一维数组a中的位置k的计算公式:
* 1、当i大于或等于j时,k = (i * (i + 1)) / 2 + j (下三角)
* 2、当i小于j时,k = (j * (j + 1)) / 2 + i (上三角)
*
*/
//返回压缩存储a中a[i][j]的值
int value(int a[], int i, int j)
{
if(i >= j)
return a[(i * (i + 1)) / 2 + j];
else
return a[(j * (j + 1)) / 2 + i];
}
//求压缩存储a和b的和
void madd(int a[], int b[], int c[][N])
{
int i, j;
for(i = 0; i < N; i++)
{
for(j = 0; j < N; j++)
{
c[i][j] = value(a, i, j) + value(b, i, j);
}
}
}
//求压缩存储a和b的乘积
void mult(int a[], int b[], int c[][N])
{
int i, j, k, sum;
for(i = 0; i < N; i++)
{
for(j = 0; j < N; j++)
{
sum = 0;
for(k = 0; k < N; k++)
{
sum = sum + value(a, i, k) * value(b, k, j);
}
c[i][j] = sum;
}
}
}
//输出压缩存储a
void disp1(int a[])
{
int i, j;
for(i = 0; i < N; i++)
{
for(j = 0; j < N; j++)
{
printf("%4d", value(a, i, j));
}
printf("
");
}
}
//输出对称矩阵c
static void disp2(int c[][N])
{
int i, j;
for(i = 0; i < N; i++)
{
for(j = 0; j < N; j++)
{
printf("%4d", c[i][j]);
}
printf("
");
}
}
int main()
{
int a[M] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; //对称矩阵压缩存储
int b[M] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
int c1[N][N], c2[N][N];
printf("a矩阵:
");
disp1(a);
printf("b矩阵:
");
disp1(b);
madd(a, b, c1);
printf("a+b:
");
disp2(c1);
mult(a, b, c2);
printf("a*b:
");
disp2(c2);
}