文章目錄
數組
數組的定義,特點及順序存儲
線性表的推廣- 數組
數組是我們熟悉的數據結構,可以把數組看作是線性表的推廣。
數組的特點是結構中的元素本身可以是具有某種結構的數據, 但屬於同一數據類型。
以一維數組爲基礎, 可以這樣觀察。
將二維數組看成數據元素是一維數組的一維數組。
將三維數組看成元素是二維數組的一維數組。
n維數組中, 每個數據元素受n個關係的約束。
一般來說, 在數組上不能做插入, 刪除數據元素的操作。
通常在各種高級語言中數組一旦被定義, 每一維的大小及上下界都不能改變。
取值操作: 給定一組下標, 讀其對應的數據元素。
賦值操作: 給定一組下標, 存儲或修改與其相對應的數據元素。
由於對數組一般不做插入、刪除操作; -旦建立了數組,數據元素個數和元素之間的關係就不再發生變動。
因此, 採用順序存儲結構標表示數組。
是以行爲主序(即先行後列)的順序存放,行存儲完了接着存儲下一行。
是以列爲主序(即先列後行)的順序存放,列存儲完了接着存儲下一列。
獲取地址:Loc(aij) = Loc(a1,1) + ((i - 1) * n + j - 1) * L;
特殊矩陣-壓縮存儲
對稱矩陣的壓縮存儲方式
用於縮小存儲單元
只需存儲個存儲單元.
帶狀矩陣
所需存儲空間 3 *n - 2;
存儲位置計算
LOC(ai,j ) = LOC(a1,1) + ((i - 1) * n + j - 1) * L;
LOC(ai, j) = LOC(a0,0) + (i *n + j ) * L;
例題
稀疏矩陣
稀疏矩陣中零元很多。
設m x n 矩陣中有t個非零元素且m * nt << m x n,
d = t / (m x n) d就被稱爲稀疏因子, d <= 0.05時爲稀疏矩陣。
採用順序存儲結構存儲非零元的三元組, 稱爲三元組表, 其中非零元按以行爲主序存儲。
顯然, 要唯一的表示一個稀疏矩陣, 可在存儲三元組表的同時存儲該矩陣的行, 列, 爲了方便運算, 矩陣的非零元素個個數也同時存儲。
➊三 元組表存儲的稀疏矩陣,在進行矩陣加法、減法和乘法等操作時,有時矩陣中的非零元素的位置和個數會發生很大的變化。
➊如A=A+ B,將矩陣B加到矩陣A.上,此時若還用三元組表表示法,勢必會爲了保持三元組表“以行序爲主序”而大量移動元素。爲此引入了鏈式存儲稀疏矩陣。
➊矩陣中,每一個矩陣元素aij,受兩個線性關係的約束,行關係、列關係;每一個關係都是線性的,我們可以用線性鏈表來存儲行關係、列關係;
➊這樣,aij就處於第i行的單鏈表中,也處於第j列的單鏈表中,就像處十字路口一-樣,所以我們將這種存儲結構稱之爲“十字鏈表”。
十字鏈表存儲方式
三元組矩陣的快速轉置
三元組矩陣以順序表模式對稀疏矩陣中的非零元素進行存儲, 每個元素記錄了其所在的行號,列號以及元素值, 並且非零元素在三元組表中以行號爲順序進行排列。
常規算法
快速轉置 - 基本策略
令矩陣M第j列有k個非零元素。 M的第j列構成了轉置矩陣T的第j行。
算法思想整理
轉置矩陣的思想就是實現了元素的行列互換,但我們要保證在轉置之後, 三元組依舊按照行順序存儲。
取出原來的三元表中的列元素, 依次對應於轉置三元表中的元素,三元表中元素的行則等於它的上一個列元素 的位置+ 上一個列元素中包含的元素。
總結
三元組的優點:實現了稀疏矩陣的高效存儲。
三元組的缺點:無法直接隨機存取數據元素, 對矩陣運算帶來了不便。
本節通過矩陣轉置實現了:
壓縮存儲後算法的特殊性。
優秀算法設計的技巧性和優雅性。
三元組轉置_普通轉置
#include<stdio.h>
#include<stdlib.h>
#define MaxSize 100
typedef int Elemtype;
int a[3][5] = { {1,0,0,0,8},{0,0,5,0,4}, {3,0,0,0,0} };
int aT[5][3];
typedef struct {
int r;
int c;
Elemtype d;
}TupNode;
typedef struct {
int rows;
int cols;
int nums;
TupNode data[MaxSize];
}TSMatrix;
void GreateMat(TSMatrix &t, TSMatrix &tb) {
t.rows = 3;
t.cols = 5;
t.nums = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; 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++;
}
}
}
}
void DispMat(TSMatrix t) {
if (t.nums <= 0) return;
else {
printf("轉置前矩陣的三元組順序表爲:\n");
for (int i = 0; i < t.nums; i++) {
printf("%d\t%d\t%d\n", t.data[i].r, t.data[i].c, t.data[i].d);
}
}
}
void TranTat(TSMatrix t, TSMatrix &tb) {
tb.rows = t.cols;
tb.cols = t.rows;
tb.nums = t.nums;
int k = 0;
if (t.nums != 0) {
for (int i = 0; i < t.cols; i++) {
for (int j = 0; j < t.nums; j++) {
if (t.data[j].c == i) {///i是最外層的列 這樣做的確可以保證有序性。
tb.data[k].r = t.data[j].c;
tb.data[k].c = t.data[j].r;
tb.data[k].d = t.data[j].d;
k++;
}
}
}
}
printf("轉置後矩陣的三元組順序表爲:\n");
for (int i = 0; i < tb.nums; i++) {
printf("%d\t%d\t%d\n", tb.data[i].r, tb.data[i].c, tb.data[i].d);
}
}
int main() {
TSMatrix t, tb;
GreateMat(t, tb);
DispMat(t);
TranTat(t, tb);
}