矩陣原地轉置演算法C++實現
阿新 • • 發佈:2021-01-20
普林斯頓演算法第四版1.1.13題目解決方案
矩陣轉置是線性代數中非常基礎的操作,如果從新開闢新的空間將原矩陣的資料對映到新矩陣,演算法雖然非常簡單,但是卻浪費大量空間,尤其對於矩陣規模比較大的情況。本文使用一種矩陣原地轉置演算法,保證矩陣主題不會消耗額外空間,但是使用了flag陣列來標識矩陣元素的轉移情況
核心程式碼為如下函式
void TransposeTwoArray(int* IndataPtr, size_t width, size_t height)
{
//計算flag陣列的總容量
size_t n = width * height;
//flag陣列,與原來矩陣陣列的元素對應,如果為false表明該元素未被轉移過,如果未 true,這表示該元素被轉移過,原有遍歷終止,開始新的遍歷轉移
bool* flagPtrIn = new bool[width * height]{};
//指示當前遍歷起始位置索引,從陣列第一個元素開始,一直遍歷到末尾結束
size_t currentIndex = 0;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
//內部迴圈遍歷的起始索引,如果遍歷連續,則內部迴圈,並自動計算下一個替代位置的索引
int Ini = i;
int Inj = j;
size_t srcIndex = Ini * width + Inj;
size_t dstIndex = Inj * height + Ini;
//被替代的位置的元素,需要提前取出,並且用於替換新的目的地址的元素,成為新的原地址元素
int preValue= IndataPtr[srcIndex];
//當從一個元素位置開始轉移替換,檢查要被替換的位置是否被遍歷過,如果被替換過,則替換內迴圈,開始去新的位置迭代,如果目的位置未被替代過,將其flag改為true,並進去替代,知道完整一個閉環
while (flagPtrIn[dstIndex] == false && currentIndex < width * height)
{
flagPtrIn[dstIndex] = true;
int tmp = IndataPtr[dstIndex];
IndataPtr[dstIndex] = preValue;
//根據新矩陣一維陣列的索引反算出原矩陣索引位置
Ini = dstIndex / width;
Inj = dstIndex % width;
srcIndex = Ini * width + Inj;
dstIndex = Inj * height + Ini;
preValue = tmp;
}
currentIndex++;
}
}
}
函式引數為:
int* IndataPt------陣列的首地址
size_t width-------矩陣寬度
size_t height------矩陣高度
測試函式
/*int dataArray[3][4]= { 1,2,3,4,5,6,7,8,9,10,11,12 };*/
int dataArray[3][1] = { 1,2,3 };
const int oldWidth = 3;
const int oldHeight = 1;
const int newWidth = 1;
const int newHeight = 3;
//列印原來陣列
for (int i = 0; i < oldHeight; i++)
{
for (int j = 0; j < oldWidth; j++)
cout << " " << dataArray[i][j];
cout << endl;
}
TransposeTwoArray((int*)dataArray, oldWidth, oldHeight);
for (int i = 0; i < newHeight; i++)
{
for (int j = 0; j < newWidth; j++)
cout << " " << *((int*)dataArray + i * newWidth + j);
cout << endl;
}
測試結果