1. 程式人生 > >《資料結構與演算法設計》實驗報告書之字串和陣列的基本操作

《資料結構與演算法設計》實驗報告書之字串和陣列的基本操作

《資料結構與演算法設計》實驗報告書之字串和陣列的基本操作

實驗專案
       字串和陣列的基本操作

實驗目的
       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;
		}
	}
}