• 数据结构上机实验(6)


    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);
    }
    

  • 相关阅读:
    【python学以致用】给PDF添加书签目录,Python解析书签JSON python王者归来 带书签版
    Difference between os.path.exists and os.path.isfile?
    Python的os.listdir配合os.path.isdir不返回目录
    selenium + geckodriver报 Message: Unable to find a matching set of capabilities
    TypeError: string argument without an encoding
    使用gevent时遇到的一些问题记录
    【JavaSE】基本类型包装类(以Integer代表)
    【JavaSE】其他常用类:Math、Random、Calendar、System
    【JavaSE】黑马程序员 刘意 基础部分笔记
    【JavaSE】集合容器的总结(全)
  • 原文地址:https://www.cnblogs.com/wangzheming35/p/13036207.html
Copyright © 2020-2023  润新知