第十二章 數據結構 數組和廣義表 + 矩陣的存儲 + 稀疏矩陣 + 三元組轉置的代碼實現

數組

數組的定義,特點及順序存儲

線性表的推廣- 數組

數組是我們熟悉的數據結構,可以把數組看作是線性表的推廣。
數組的特點是結構中的元素本身可以是具有某種結構的數據, 但屬於同一數據類型。
以一維數組爲基礎, 可以這樣觀察。
將二維數組看成數據元素是一維數組的一維數組。
將三維數組看成元素是二維數組的一維數組。

在這裏插入圖片描述在這裏插入圖片描述

n維數組中, 每個數據元素受n個關係的約束。
一般來說, 在數組上不能做插入, 刪除數據元素的操作。
通常在各種高級語言中數組一旦被定義, 每一維的大小及上下界都不能改變。
取值操作: 給定一組下標, 讀其對應的數據元素。
賦值操作: 給定一組下標, 存儲或修改與其相對應的數據元素。

由於對數組一般不做插入、刪除操作; -旦建立了數組,數據元素個數和元素之間的關係就不再發生變動。

因此, 採用順序存儲結構標表示數組。

是以行爲主序(即先行後列)的順序存放,行存儲完了接着存儲下一行。
是以列爲主序(即先列後行)的順序存放,列存儲完了接着存儲下一列。
在這裏插入圖片描述
在這裏插入圖片描述在這裏插入圖片描述獲取地址:Loc(aij) = Loc(a1,1) + ((i - 1) * n + j - 1) * L;

特殊矩陣-壓縮存儲

在這裏插入圖片描述

對稱矩陣的壓縮存儲方式

在這裏插入圖片描述

用於縮小存儲單元
aij=ajiaij = aji
只需存儲n(n+1)/2n * (n + 1) / 2個存儲單元.

在這裏插入圖片描述在這裏插入圖片描述
在這裏插入圖片描述在這裏插入圖片描述

在這裏插入圖片描述在這裏插入圖片描述

帶狀矩陣

在這裏插入圖片描述

所需存儲空間 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列的單鏈表中,就像處十字路口一-樣,所以我們將這種存儲結構稱之爲“十字鏈表”。

在這裏插入圖片描述

十字鏈表存儲方式

在這裏插入圖片描述

三元組矩陣的快速轉置

三元組矩陣以順序表模式對稀疏矩陣中的非零元素進行存儲, 每個元素記錄了其所在的行號,列號以及元素值, 並且非零元素在三元組表中以行號爲順序進行排列。
在這裏插入圖片描述
在這裏插入圖片描述
常規算法dest[col][row]=source[row][col]dest[col][row] = source[row][col]
O(mn)O(m * n)

快速轉置 - 基本策略

令矩陣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);
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章