《資料結構與演算法設計》實驗報告書之字串和陣列的基本操作
《資料結構與演算法設計》實驗報告書之字串和陣列的基本操作
實驗專案
字串和陣列的基本操作
實驗目的
1.掌握陣列的定義
2.理解求稀疏矩陣的轉置矩陣演算法在三元組表示上的實現。
實驗內容
1.利用C語言實現陣列的定義。
2.實現稀疏矩陣的三元組表示以及轉置演算法。
演算法設計分析
(一)資料結構的定義
有時候我們的矩陣中只有零星的一些非零元素,其餘的都是零元素,那麼我們稱之為稀疏矩陣,當然沒有絕對的說有多少個零元素才算稀疏。簡單說,稀疏矩陣就是非零元素個數遠遠小於元素個數的矩陣。相對於稀疏矩陣來說,一個不稀疏的矩陣也稱作稠密矩陣。針對上面的這個無規律的存放非零元素,三元組提出了一種方法,就是僅僅記錄矩陣中的非零元素以及它的行,列以及值N(x,y,v)構成的一個三元組,標識一個稀疏矩陣的話,還要記錄該矩陣的階數,這樣我們就將一個二維的變成了一個一維,極大的壓縮的儲存空間。 這裡要注意的就是,三元組的構建採用“行”是從上到下,“列”也是從左到右的方式構建的順序表。
順序表儲存結構定義為:
/*定義稀疏矩陣三元組*/
#define MAXSIZE 12500
typedef struct {
int i, j; //該非零元的行列下標
int e;
}Triple;
typedef struct {
Triple data[MAXSIZE];
int mu, nu, tu;
//矩陣的行、列數和非零元個數
}TSMatrix;
(二)總體設計
實驗總共包括五個函式:主函式,初始化稀疏矩陣三元組函式,列印稀疏矩陣三元組函式,轉置稀疏矩陣三元組函式,快速轉置稀疏矩陣三元組函式。
主函式:統籌呼叫各個函式以實現相應功能
Int main()
Void opration()
初始化稀疏矩陣三元組函式:建立初始化稀疏矩陣三元組
Void init ()
列印稀疏矩陣三元組函式:列印稀疏矩陣三元組構成的稀疏矩陣
Int Print()
轉置稀疏矩陣三元組函式:利用普通方法遍歷轉置稀疏矩陣
Void exchange()
快速轉置稀疏矩陣三元組函式:利用快速方法直接轉置稀疏矩陣
Void quickly ()
(三)各函式的詳細設計:
主函式main()
主要就是進行功能的實現。
初始化稀疏矩陣三元組函式init():
建立初始化稀疏矩陣三元組,初始行,列,值的個數,再一一存入資料。
列印稀疏矩陣三元組函式Print()
將稀疏矩陣三元組構成的稀疏矩陣以陣列的方式打印出來。
轉置稀疏矩陣三元組函式exchange()
利用普通方法遍歷轉置稀疏矩陣,兩層迴圈直接巢狀遍歷整個二維陣列,複雜度較高,效率不大。
快速轉置稀疏矩陣三元組函式quickly()
利用快速方法遍歷轉置稀疏矩陣,直接使用一層迴圈,再遍歷資料的同時把位置記下來,在其中找的時候直接把值放在了指定的位置,比起普通的方法快了很多。
實驗測試結果
實驗總結:(100字到200字)
(1)除錯過程中主要遇到哪些問題?是如何解決的?
答:稀疏矩陣三元組的難度有點大,遇見的問題有一些。
1.在一開始列印時遇見資料打印不出來的問題,結果發現是由於初始化函式傳值時沒有使用&符號,導致三元組的數沒有傳入。
2.在進行普通轉置函式的時候,沒有想到需要用兩個三元組來存放資料,導致走了很多的歪路,後來發現,有另一個三元組來存放資料比較方便快捷。
3.在快速轉置的函式中,有些地方的邏輯還是不怎麼清楚,需要加深理解,尤其是找位置的陣列是如何來的。
(2)經驗和體會
答:還是那句老話,多敲程式碼自己練習,有時間把多複習多看看書,增加自己對快速轉置的理解能力。
附錄 實驗程式程式碼(該部分請加註釋)
/SeqList.h函式程式碼/
//#ifndef SEQLIST_H_INCLUDED
//#define SEQLIST_H_INCLUDED
#define MAXSIZE 12500
typedef struct {
int i, j; //該非零元的行列下標
int e; //該元素的值
}Triple;
typedef struct {
Triple data[MAXSIZE];
int mu, nu, tu;
//矩陣的行、列數和非零元個數
}TSMatrix;
void init(TSMatrix &s)
{
int i;
std::cout<<"請輸入需要打的行,列,值!!"<<std::endl;
std::cin>>s.mu>>s.nu>>s.tu; //輸入每個值得位置以及值
for(i=0;i<s.tu;i++){//迴圈輸入
std::cout<<"請輸入第"<<i+1<<"的行號,列號,值:"<<std::endl;
std::cin>>s.data[i].i>>s.data[i].j>>s.data[i].e;
}
}
void Print(TSMatrix t)//列印函式
{
int time=0,i,j;
for(i=0;i<t.mu;i++)
for(j=0;j<t.nu;j++)
{
if(t.data[time].i==i&&t.data[time].j==j)//壓縮矩陣不斷輸出
{
std::cout<<t.data[time].e;
time++;
}
else
std::cout<<"0";
if(j!=t.nu-1)//格式控制
std::cout<<" ";
else
std::cout<<std::endl;
}
}
void exchange(TSMatrix s,TSMatrix &t){//普通轉置函式
t.mu=s.nu; t.nu=s.mu; t.tu=s.tu;//直接交換兩個三元組得行數和列數
if (t.tu)//如果值的個數不為零就進入程式
{
int q = 0;//第二個三元組的下標
for (int col = 0; col < s.nu; col++){//按照順序來迴圈找值
for (int p = 0; p < s.tu; p++){//遍歷每個資料
if ( s.data[p].j == col )//如果對應的位置有值,則進入下面語句
{
t.data[q].i = s.data[p].j ;//交換行和列
t.data[q].j = s.data[p].i ;
t.data[q].e = s.data[p].e;//賦值
++ q;//下標加加
}
}
}
}
}
void quickly(TSMatrix M,TSMatrix &T)//快速轉置函式
{
int num[200],cpot[200],q,col,t,p;//定義兩個陣列,第一個用來統計相同列的個數,另一個用來求位置。
T.mu = M.nu; T.nu = M.mu; T.tu = M.tu;//交換
if (T.tu) {
for ( col=0; col<M.nu; ++col)
num[col] = 0;//初始化
for ( t=0; t<M.tu; ++t)
num[M.data[t].j]++;//統計相同列的個數
// 求 M 中各列非零元的個數
cpot[0] = 0;
for ( col=1;col<M.nu;col++)
cpot[col] = cpot[col -1] + num[col -1];//求位置
for ( p=0; p<M.tu; ++p) { // 轉置矩陣元素
col = M.data[p].j;
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];//進行完之後加1,表示往後移動一位
}
}
}
//#endif // SEQLIST_H_INCLUDED
/menu.h選單函式程式碼/
#ifndef MENU_H_INCLUDED
#define MENU_H_INCLUDED
void menu(){
std::cout<<"\n";
std::cout<<" ************************矩陣轉置************************\n";
std::cout<<" * *\n";
std::cout<<" * a:建立矩陣 b:轉置矩陣 *\n";
std::cout<<" * c:列印矩陣 d:快速轉置矩陣 *\n";
std::cout<<" * e:退出 *\n";
std::cout<<" * *\n";
std::cout<<" ********************************************************\n";
}
#endif // MENU_H_INCLUDED
/主函式程式碼/
#include <iostream>
#include "menu.h"
#include "Array.h"
using namespace std;
int main()
{
void opration();
opration();
return 0;
}
void opration(){
for(;;){
TSMatrix s,t,r;
menu();
char a;
cin>>a;
switch(a){
case 'a':
init(s);
Print(s);
break;
case 'b':
exchange(s,t);
cout<<"轉置之前的矩陣為:"<<endl;
Print(s);
cout<<"轉置之後的矩陣為:"<<endl;
Print(t);
break;
case 'c':
cout<<"列印的矩陣為:"<<endl;
Print(s);
break;
case 'd':
quickly(s,r);
cout<<"快速轉置之前的矩陣為:"<<endl;
Print(s);
cout<<"快速轉置之後的矩陣為:"<<endl;
Print(r);
break;
case 'e':
cout<<"拜拜!!"<<endl;
return ;
break;
default:
cout<<"你輸入的序號不正確!!"<<endl;
break;
}
}
}