C++实现矩阵原地转置算法_C 语言

本文实例描述了C++实现矩阵原地转置算法,是一个非常经典的算法,相信对于学习C++算法的朋友有很大的帮助。具体如下:

一、问题描述

微软面试题:将一个MxN的矩阵存储在一个一维数组中,编程实现矩阵的转置。

要求:空间复杂度为O(1)

二、思路分析

下面以一个4x2的矩阵A={1,2,3,4,5,6,7,8}进行分析,转置过程如下图:

图中右下角的红色数字表示在一维数组中的下标。矩阵的转置其实就是数组中元素的移动,具体的移动过程如下图:

我们发现,这些移动的元素的下标是一个个环,下标1的元素移动到4,下标4的元素移动到2,下标2的元素移动到1。在编写程序的时候,我们需要解决两个问题:第一个是如何判定环是否重复(已处理过);第二个是如何计算当前元素下标的前驱与后继。

第一个问题:如何判断环是重复已处理过的?因为我们遍历整个数组时下标是从小到大的,所以如果是第一次遍历该环,则第一个下标肯定是这个环中最小的。如果一个环被处理过,那么总能找到一个它的后继是小于它的。从上图可以明显看出来。

第二个问题:如何计算当前元素下标的前驱与后继?假设转置前某个元素的数组下标为i,则它所在行列为(i/N, i%N),转置后所在行列则为(i%N, i/N),可计算转置后数组下标为(i%N)*M+i/N,此为i的后继。假设转置后某个元素的数组下标为i,则它所在行列为(i/M, i%M),则转置前所在行列为(i%M, i/M),可计算此时下标为(i%M)*N+i/M,此为i的前驱。

三、代码实现如下:

/*************************************************************************
  > File Name: matrix_transpose.cpp
  > Author: SongLee
 ************************************************************************/
#include<iostream>
using namespace std; 

/* 后继 */
int getNext(int i, int m, int n)
{
  return (i%n)*m + i/n;
} 

/* 前驱 */
int getPre(int i, int m, int n)
{
  return (i%m)*n + i/m;
} 

/* 处理以下标i为起点的环 */
void movedata(int *mtx, int i, int m, int n)
{
  int temp = mtx[i]; // 暂存
  int cur = i;    // 当前下标
  int pre = getPre(cur, m, n);
  while(pre != i)
  {
    mtx[cur] = mtx[pre];
    cur = pre;
    pre = getPre(cur, m, n);
  }
  mtx[cur] = temp;
} 

/* 转置,即循环处理所有环 */
void transpose(int *mtx, int m, int n)
{
  for(int i=0; i<m*n; ++i)
  {
    int next = getNext(i, m, n);
    while(next > i) // 若存在后继小于i说明重复
      next = getNext(next, m, n);
    if(next == i)  // 处理当前环
      movedata(mtx, i, m, n);
  }
} 

/* 输出矩阵 */
void print(int *mtx, int m, int n)
{
  for(int i=0; i<m*n; ++i)
  {
    if((i+1)%n == 0)
      cout << mtx[i] << "\n";
    else
      cout << mtx[i] << " ";
  }
} 

/* 测试 */
int main()
{
  int matrix[4*2] = {1,2,3,4,5,6,7,8};
  cout << "Before matrix transposition:" << endl;
  print(matrix, 4, 2);
  transpose(matrix, 4, 2);
  cout << "After matrix transposition:" << endl;
  print(matrix, 2, 4);
  return 0;
} 

运行结果如下图所示:

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索c++
, 算法
, 矩阵
原地转置
矩阵 原地转置、矩阵转置算法、稀疏矩阵快速转置算法、稀疏矩阵的转置算法、矩阵的快速转置算法,以便于您获取更多的相关知识。

时间: 2024-10-27 14:45:02

C++实现矩阵原地转置算法_C 语言的相关文章

c语言-关于矩阵快速转置算法问题

问题描述 关于矩阵快速转置算法问题 请问圈出的部分是什么意思啊 解决方案 图片看不清,应该和这个类似,而且有详细注释:http://programdesign.baike.com/article-379765.html 解决方案二: 7. 矩阵的快速转置算法矩阵的快速转置矩阵的快速转置

详细总结C++的排序算法_C 语言

排序算法经过了很长时间的演变,产生了很多种不同的方法.对于初学者来说,对它们进行整理便于理解记忆显得很重要.每种算法都有它特定的使用场合,很难通用.因此,我们很有必要对所有常见的排序算法进行归纳. 我不喜欢死记硬背,我更偏向于弄清来龙去脉,理解性地记忆.比如下面这张时间复杂度图,我们将围绕这张图来分析. 上面的这张图来自一个PPT.它概括了数据结构中的所有常见的排序算法,给大家总结如下. 区分稳定与不稳定:快速.希尔.堆.选择不稳定,其他排序算法均稳定. 平均时间复杂度:冒泡,选择,插入是O(n

C语言实现斗地主的核心算法_C 语言

数据结构只选择了顺序表,没有选择链表,灵活性和抽象性不足,不能普适. head.h #ifndef __HEAD_H__ #define __HEAD_H__ #define MAXLEVEL 15 typedef struct CARD{ int number; int level; char *flower; char point; }card;//卡 typedef struct DECK{ int top; int arr[55]; }deck;//牌堆 typedef struct P

C++实现N个骰子的点数算法_C 语言

本文实例讲述了C++实现N个骰子的点数算法,分享给大家供大家参考之用.具体方法如下: 题目要求:把n个骰子仍在地上,所有点数 实现代码如下: #include <iostream> using namespace std; const int g_maxValue = 6; const int number = 6; int array[(number - 1) * g_maxValue + 1]; void probility(int original, int current, int s

C++实现查找中位数的O(N)算法和Kmin算法_C 语言

本文实例讲述了C++实现查找中位数的O(N)算法和Kmin算法,分享给大家供大家参考.具体方法如下: 利用快速排序的partition操作来完成O(N)时间内的中位数的查找算法如下: #include <iostream> #include <cassert> #include <algorithm> #include <iterator> using namespace std; int array[] = {1, 2, 10, 8, 9, 7, 5};

C语言实现二叉树遍历的迭代算法_C 语言

本文实例讲述了C语言实现二叉树遍历的迭代算法,是数据结构算法中非常经典的一类算法.分享给大家供大家参考. 具体实现方法如下: 二叉树中序遍历的迭代算法: #include <iostream> #include <stack> using namespace std; struct Node { Node(int i, Node* l = NULL, Node* r = NULL) : item(i), left(l), right(r) {} int item; Node* le

c++中八大排序算法_C 语言

概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 我们这里说说八大排序就是内部排序. 当n较大,则应采用时间复杂度为O(nlog2n)的排序方法:快速排序.堆排序或归并排序序. 快速排序:是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短:  1.插入排序-直接插入排序(Straight Insertion Sort) 基本思想: 将一个记录插入

C语言 实现归并排序算法_C 语言

C语言 实现归并排序算法 归并排序(Merge sort)是创建在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用. 一个归并排序的例子:对一个随机点的链表进行排序 算法描述 归并操作的过程如下: 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列 设定两个指针,最初位置分别为两个已经排序序列的起始位置 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置 重复步骤3直到某一指针到达序列尾

C语言实现字符串匹配KMP算法_C 语言

字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD"? 下面的的KMP算法的解释步骤 1. 首先,字符串"BBC ABCDAB ABCDABCDABDE"的第一个字符与搜索词"ABCDABD"的第一个字符,进行比较.因为B与A不匹配,所以搜索词后移一位. 2. 因为B与A不匹配,搜索词再往后移. 3. 就这样,直到字符