首页 > 其他分享 >稀疏矩阵 - 十字链表 & 快速转置

稀疏矩阵 - 十字链表 & 快速转置

时间:2024-05-11 18:11:35浏览次数:14  
标签:转置 矩阵 链表 int num cpot

十字链表

每个稀疏矩阵非零元素都是一个结点,数据域存储的是所在行、所在列和元素值,有两个指针域,分别存储的是指向与该元素同行的下一个非零元素和同列的下一个非零元素的指针。

所以一个m行n列的稀疏矩阵,(最多)总共有(m + n)个链表,即(在每行每列都有非零元素的情况下,当然这样可能并不算是一个“好的”稀疏矩阵)每行每列都有一个链表。

每个链表都有其头结点,这些头结点使用顺序表存储,便于存取。

快速转置

如果需要将一个使用三元组形式存储的稀疏矩阵进行转置,当然可以直接交换每一个结点的行和列。但这样做的问题在于,原矩阵是按行数升序排列的,转置之后的矩阵就会变为无序的。
快速转置算法的目的就在于得到一个同样有序排列的转置后矩阵。

三元组和稀疏数组定义

#define MAXSIZE 12500

typedef int ElemType;
typedef struct {
    int i, j;
    ElemType e;
} Triple;
typedef struct {
    Triple data[MAXSIZE + 1];
    int mu, nu, tu; // 行数 列数 非零元个数
} TSMatrix;

如果我们能在进行转置之前就知道原矩阵的每一个非零元将位于新矩阵的哪个位置,就可以直接将其放在对应位置上,进而就可以得到有序的新矩阵。

需要借助两个额外的矩阵:

  1. num[]表示原矩阵每列中非零元的个数。
  2. cpot[]表示原矩阵中每一列的第一个非零元在新矩阵(也就是新矩阵每一行)中的位置。其中有如下两个公式:
    cpot[1] = 1
    cpot[col] = cpot[col - 1] + num[col - 1]

快速转置函数代码

void FastTranspose(TSMatrix M, TSMatrix &T) {
    T.mu = M.nu, T.nu = M.mu, T.tu = M.tu;
    if(T.tu) {
        int col, num[105], cpot[105];
        memset(num, 0, sizeof(num));
        memset(cpot, 0, sizeof(cpot));
        for(int i = 1; i <= M.tu; i++) num[M.data[i].j]++; // 每列的非零元个数
        cpot[1] = 1; // 第一行第一列的元素
        for(col = 2; col <= M.nu; col++) cpot[col] = num[col - 1] + cpot[col - 1]; // 每个非零元在新数组中的位置
        for(int p = 1; p <= M.tu; p++) {
            col = M.data[p].j;
            int q = cpot[col];
            T.data[q].i = M.data[p].j;
            T.data[q].j = M.data[p].i;
            T.data[q].e = M.data[p].e;
            cpot[col]++; // 切换到原矩阵的下一个非零元
        }
    }
}

即可直接得到有序的转置后新矩阵。
*需要注意for循环中临时变量的范围,容易写错。

标签:转置,矩阵,链表,int,num,cpot
From: https://www.cnblogs.com/ww0809/p/18186958

相关文章

  • 代码随想录训练营第三天 | 203.移处链表元素 707.设计链表 206.反转链表
    203.移除链表元素题目链接https://leetcode.cn/problems/remove-linked-list-elements/文章讲解https://programmercarl.com/0203.移除链表元素.html#算法公开课视频讲解https://www.bilibili.com/video/BV18B4y1s7R9/?vd_source=2b5b33d3d692b0064daff4e58957fc82tips:对......
  • 手撕链表(自存)
    #include<stdio.h>#include<stdlib.h>typedefintE;typedefstructnode{Eval;structnode*next;}ListNode;ListNode*list_creat(){ListNode*list=malloc(sizeof(ListNode));returnlist;}voidpush_back(ListNode*List......
  • 代码随想录训练营第二天 | 977.有序数组的平方 209.长度最小的子数组 59.螺旋矩阵II
    977.有序数组的平方题目链接:https://leetcode.cn/problems/squares-of-a-sorted-array/文章讲解:https://programmercarl.com/0977.有序数组的平方.html视频讲解:https://www.bilibili.com/video/BV1QB4y1D7ep暴力解时间复杂度O(nlogn)空间复杂度O(1)双指针法时间复......
  • 力扣刷题笔记-21 合并两个有序链表
    其实不回答就是答案双指针classSolution{publicListNodemergeTwoLists(ListNodelist1,ListNodelist2){ListNodedummy=newListNode(-1);ListNodep=dummy;ListNodep1=list1,p2=list2;while(p1!=null&&p2!=nu......
  • 删除单向链表中数据最小的结点
    (1)算法的基本设计思想要找到链表中数据最小的结点,可以使用4指针法。具体步骤如下:定义4个指针,分别命名为MinNodeprev、MinNode、CurrentNodePrev、CurrentNode,MinNodeprev、CurrentNodePrev指向链表的头结点,MinNode、CurrentNode指向链表的首结点。同时移动CurrentNodePrev、Cur......
  • 矩阵之间的关系简单整理
    等价:可以通过初等变换互相转化的矩阵。当A和B为同型矩阵,且r(A)=r(B)时,A,B一定等价。相似:\(P^{-1}AP=B\)。本质是基坐标转换,表示在不同坐标系下效果相同的线性变换过程。P为基坐标转换矩阵,是新基向量按列排列形成的矩阵。重要性质(原理):A与B相似,则A与B有相同的特征值(亦有相同的迹与......
  • 23. 合并 K 个升序链表
    23.合并K个升序链表https://leetcode.cn/problems/merge-k-sorted-lists/?envType=study-plan-v2&envId=top-interview-150 思路K个升序链表,依据显然的规则:当前最小的值,肯定出自于K个升序链表的K个表头中,对这K个表头使用最小堆(priority_queue)进行管理,pop出的堆顶值,就......
  • 74. 搜索二维矩阵
    给你一个满足下述两条属性的mxn整数矩阵:每行中的整数从左到右按非严格递增顺序排列。每行的第一个整数大于前一行的最后一个整数。给你一个整数target,如果target在矩阵中,返回true;否则,返回false。示例1:输入:matrix=[[1,3,5,7],[10,11,16,20],[23,30,34,60]],t......
  • 关于单向不循环链表的创建、插入、删除、遍历、检索
    关于单向不循环链表的创建、插入、删除、遍历、检索单向不循环链表公式初始化单向不循环链表构建单向不循环链表结构体//创建结构体类型typedefstructone_way_node{//数据域chardata[DATA_LEN];//指针域structone_way_node*next;}ONE_WAY_NOD......
  • Leetcode --- 203. 移除链表元素
    题目描述给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val==val 的节点,并返回 新的头节点 。示例1: 示例输入:head=[1,2,6,3,4,5,6],val=6输出:[1,2,3,4,5]输入:head=[7,7,7,7],val=7输出:[]参考实现方式1、使用递归实现......