1. 程式人生 > >《演算法導論》上機總結

《演算法導論》上機總結

突然想到把所有的上機都總結一下。如果有錯誤還請不吝斧正。

目錄

實驗一 排序演算法

實驗二 Strassen’s 矩陣乘法和最近點對演算法

實驗三:作業排程和最長共同子序列算

實驗四:單源最短路徑和全點對最短路徑演算法


首先說明一下程式碼格式:我這邊所有的東西基本都寫到 了一起。就像這樣:

然後執行的時候只要把我程式碼中的Test函式放到主函式裡就可以了。就像這樣(記得把標頭檔案加進去):

 


實驗一 排序演算法

插入排序演算法(直接插入、二分插入)

合併排序演算法

快速排序演算法

隨機快速排序演算法

計數排序演算法

基數排序演算法

桶排序演算法(沒寫)

直接插入排序.h

#pragma once
typedef int dataType;

/*列印陣列*/
void PrintArray(dataType arr[], int length);

/*陣列初始化*/
void InitArray(dataType arr[], int length);

/*直接插入排序*/
void DirectInsertSort(dataType arr[], int length);

/*直接插入排序的測試函式*/
void TestDirectInsrtSort();

直接插入排序.cpp

#include "直接插入排序.h"
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;

/*列印陣列*/
void PrintArray(dataType arr[], int length)
{
	for (int i = 0; i < length; i++)
	{
		if (arr[i] > 0)
			cout << arr[i] << "  ";
	}
	cout << endl;
}

/*陣列初始化*/
void InitArray(dataType arr[], int length)
{
	srand((unsigned)time(NULL));/*設定隨機數種子*/
	arr[0] = -1;/*第一位要留出來用來插入*/

	for (int i = 1; i < length; i++)
	{
		arr[i] = rand() % 91 + 10;/*rand()%(Y-X+1)+X,生成X-Y之間的數*/
	}
}

/*直接插入排序*/
void DirectInsertSort(dataType arr[], int length)
{
	arr[0] = arr[1];/*先把陣列第一個陣列插入到第一位*/
	for (int i = 2; i < length; i++)
	{
		for (int j = i - 2; j >= 0; j--)
		{
			/*如果未排序的數比已經排序好的最後一個數要大,就插入到末尾,同時對下一個進行判斷*/
			if (arr[i] >= arr[j])
			{
				arr[j + 1] = arr[i];
				break;
			}
			/*否則就將前面的數一個個後移*/
			else
			{
				arr[j + 1] = arr[j];
				if (0 == j)
					arr[0] = arr[i];
			}
		}
	}
	/*排序完成後最後一位置空*/
	arr[length - 1] = -1;
}

/*直接插入排序的測試函式*/
void TestDirectInsrtSort()
{
	int length;
	cout << "輸入你理想的陣列長度:";
	cin >> length;
	length++;/*我們的需要的陣列得多一位*/
	dataType *arr = new dataType[length + 1];/*建立一個一維陣列*/
	InitArray(arr, length);/*初始化陣列*/
	PrintArray(arr, length);/*列印這個陣列*/
	DirectInsertSort(arr, length);/*對這個陣列進行直接插入排序*/
	PrintArray(arr, length);/*再次列印這個陣列*/
	delete[] arr;/*銷燬這個陣列*/
}

實驗結果:

二分排序.h

#pragma once
typedef int dataType;

/*列印陣列*/
void PrintTwoSortArray(dataType arr[], int length);

/*陣列初始化*/
void InitTwoSortArray(dataType arr[], int length);

/*二分排序*/
void TwoSort(dataType arr[], int length);

/*二分排序的測試函式*/
void TestTwoSort();

二分排序.cpp

#include "二分排序.h"
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;


/*列印陣列*/
void PrintTwoSortArray(dataType arr[], int length)
{
	for (int i = 0; i < length; i++)
	{
		if (arr[i] > 0)
			cout << arr[i] << "  ";
	}
	cout << endl;
}

/*陣列初始化*/
void InitTwoSortArray(dataType arr[], int length)
{
	srand((unsigned)time(NULL));/*設定隨機數種子*/
	arr[0] = -1;/*第一位要留出來用來插入*/

	for (int i = 1; i < length; i++)
	{
		arr[i] = rand() % 91 + 10;/*rand()%(Y-X+1)+X,生成X-Y之間的數*/
	}
}

/*二分排序*/
void TwoSort(dataType arr[], int length)
{
	/*一開始我們還是先把第一個數字插入到陣列頭部*/
	arr[0] = arr[1];

	/*接下來才開始二分插入,從arr[2]開始插入,所以i=2*/
	for (int i = 2; i < length; i++)
	{
		int left = 0;
		int right = i - 2;/*arr[i-2]才是已經排序好的陣列的最後一位*/
		while (left <= right)
		{
			int mid = (left + right) >> 1;/*相當於(left + right)÷2*/
										  /*調整要折半的陣列範圍,根據left與right的值來變化*/
			if (arr[mid] > arr[i])
			{
				right = mid - 1;
			}
			else
			{
				left = mid + 1;
			}
		}
		for (int j = i - 2; j > right; j--)
		{
			arr[j + 1] = arr[j];
		}
		arr[right + 1] = arr[i];
	}
	arr[length - 1] = -1;/*最後一位置空*/
}

/*二分排序的測試函式*/
void TestTwoSort()
{
	int length;
	cout << "輸入你想要的陣列長度:";
	cin >> length;
	length++;/*我們的需要的陣列得多一位*/
	dataType *arr = new dataType[length];/*建立一個一維陣列*/
	InitTwoSortArray(arr, length);/*初始化陣列*/
	PrintTwoSortArray(arr, length);/*列印這個陣列*/
	TwoSort(arr, length);/*對這個陣列進行直接插入排序*/
	PrintTwoSortArray(arr, length);/*再次列印這個陣列*/
	delete[] arr;/*銷燬這個陣列*/
}

實驗結果:

合併排序(歸併排序)演算法.h

#pragma once

typedef int dataType;

/*列印陣列*/
void PrintMergeArray(dataType arr[], int length);

/*陣列初始化*/
void InitMergeArray(dataType arr[], int length);

/*合併*/
void Merge(dataType sourceArr[], dataType tempArr[], int start, int middle, int end);

/*分解遞迴*/
void MergeSort(dataType sourceArr[], dataType tempArr[], int start, int end);

/*歸併排序測試函式*/
void TestMergeSort();

合併排序(歸併排序)演算法.cpp

#include "歸併排序.h"
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
using namespace std;


/*列印陣列*/
void PrintMergeArray(dataType arr[], int length)
{
	for (int i = 0; i < length; i++)
	{
		cout << arr[i] << " ";
		if ((i + 1) % 10 == 0)/*每輸出5個數字就換行*/
			cout << endl;
	}
	cout << endl;
}

/*陣列初始化*/
void InitMergeArray(dataType arr[], int length)
{
	srand((unsigned)time(NULL));/*設定隨機數的種子*/
	for (int i = 0; i < length; i++)
	{
		arr[i] = rand() % 100 + 1;/*陣列為1~100的隨機數*/
	}
}

/*合併*/
void Merge(dataType sourceArr[], dataType tempArr[], int start, int middle, int end)
/*sourceArr[]是原陣列,tempArr[]中間臨時陣列*/
{
	int i = start, j = middle + 1, k = start;/*i~mid為左邊陣列,j~end為右邊陣列*/
											 /*我們要把左邊和右邊陣列歸併在一起*/
	while (i != middle + 1 && j != end + 1)/*如果左右兩個陣列都還有數殘留*/
	{
		if (sourceArr[i] > sourceArr[j])/*左邊陣列第一個數大於右邊陣列第一個數,就把右邊陣列第一個數放到合併陣列的第一位*/
			tempArr[k++] = sourceArr[j++];
		else/*反之,把左邊陣列第一個數放到合併陣列的第一位*/
			tempArr[k++] = sourceArr[i++];
	}
	/*如果其中一個數組結束了而另一個數組還沒有結束,就把另一個數組剩下的數都放到合併的數組裡*/
	while (i != middle + 1)
	{
		tempArr[k++] = sourceArr[i++];
	}
	while (k != end + 1)
	{
		tempArr[k++] = sourceArr[j++];
	}
	/*把合併後的陣列放到原陣列中*/
	for (i = start; i <= end; i++)
	{
		sourceArr[i] = tempArr[i];
	}
}

/*分解遞迴*/
void MergeSort(dataType sourceArr[], dataType tempArr[], int start, int end)
{
	int middle;
	if (start < end)/*如果陣列中還有超過兩個數就繼續遞迴*/
	{
		middle = (start + end) >> 1;/*middle = (start + end)÷2*/
		MergeSort(sourceArr, tempArr, start, middle);/*對左邊的陣列進行分解*/
		MergeSort(sourceArr, tempArr, middle + 1, end);/*對右邊的陣列進行分解*/
		Merge(sourceArr, tempArr, start, middle, end);/*將左右分解完成後的陣列進行歸併*/
	}
}

/*歸併排序測試函式*/
void TestMergeSort()
{
	int length;
	cout << "輸入你期望的陣列長度:";
	cin >> length;
	dataType *sourceArr = new dataType[length];
	dataType *tempArr = new dataType[length];
	InitMergeArray(sourceArr, length);
	for (int i = 0; i < length; i++)
	{
		tempArr[i] = sourceArr[i];
	}
	cout << "原來的陣列為:" << endl;
	PrintMergeArray(sourceArr, length);
	MergeSort(sourceArr, tempArr, 0, length - 1);
	cout << "歸併排序後的陣列為:" << endl;
	PrintMergeArray(sourceArr, length);
	delete[] sourceArr;
	delete[] tempArr;
}

實驗結果:

快速排序演算法.h(隨機快速排序演算法寫在一起了)

#pragma once
typedef int dataType;

/*列印陣列*/
void PrintQuickArray(dataType arr[], int length);

/*初始化陣列*/
void InitQuickArray(dataType arr[], int length);

/*快速排序遞迴部分*/
void QuickSort(dataType arr[], int left, int right);

/*快速排序主體部分*/
int Partition(dataType arr[], int left, int right);

/*快速排序的隨機化版本*/
int RandomPartition(dataType arr[], int left, int right);

/*快速排序測試函式*/
void TestQuickSort();

快速排序演算法.cpp

#include "快速排序.h"
#include <stdlib.h>
#include <time.h>
#include <iostream>
using namespace std;

/*列印陣列*/
void PrintQuickArray(dataType arr[], int length)
{
	for (int i = 0; i < length; i++)
	{
		cout << arr[i] << " ";
		if ((i + 1) % 15 == 0)/*如果一排超過15個數就換行*/
			cout << endl;
	}
	cout << endl; cout << endl;
}

/*初始化陣列*/
void InitQuickArray(dataType arr[], int length)
{
	srand((unsigned)time(NULL));/*建立隨機數種子*/
	for (int i = 0; i < length; i++)
	{   /*一句廢話:雖然這裡可以不要花括號,我總覺得有了比較莊重!*/
		arr[i] = rand() % 100 + 1;/*arr[i]的值:1-100之間*/
	}
}

/*快速排序遞迴部分*/
void QuickSort(dataType arr[], int left, int right)
{
	if (left < right)
	{
		int middle = Partition(arr, left, right);/*arr[middle]左邊的數都小於它,右邊的數都大於它*/
		QuickSort(arr, left, middle - 1);/*對左邊的數進行快排*/
		QuickSort(arr, middle + 1, right);/*對右邊的數進行快排*/
	}
}

/*快速排序主體部分*/
int Partition(dataType arr[], int left, int right)
{
	if (left >= right)/*此時兩個游標重合,代表已經整理完成一個組*/
		return 0;

	/*①首先我們設定一個key*/
	int key = arr[left];
	while (left < right)
	{
		while (left<right&&arr[right] >= key)/*②right游標從右往左 ←,找到一個數小於key*/
		{
			right--;
		}
		/*把這個數賦值給left游標所在的位置*/
		arr[left] = arr[right];
		while (left < right&&arr[left] <= key)/*③left游標從左往右→,找到一個數大於key*/
		{
			left++;
		}
		/*把這個數賦值給right游標所在的位置*/
		arr[right] = arr[left];
	}
	/*④left與right游標重合,把key賦值給這兩個游標重合的位置*/
	arr[left] = key;

	/*返回重合的位置的下標*/
	return left;
}

/*快速排序的隨機化版本*/
int RandomPartition(dataType arr[], int left, int right)
{
	srand((unsigned)time(NULL));/*建立隨機種子*/
	int random = rand() % (right - left + 1) + left;/*random就是一個隨機的位置*/
													/*將arr[random]與arr[left]進行交換*/
	dataType temp = arr[left];
	arr[left] = arr[random];
	arr[random] = temp;
	return Partition(arr, left, right);
}

/*快速排序測試函式*/
void TestQuickSort()
{
	int length;
	cout << "輸入你理想的陣列長度:";
	cin >> length;/*輸入*/
	cout << endl;
	dataType *arr = new dataType[length];/*動態建立陣列*/
	InitQuickArray(arr, length);/*初始化這個陣列*/
	cout << "初始化後的陣列:  ";
	PrintQuickArray(arr, length);
	QuickSort(arr, 0, length - 1);/*對這個陣列進行快速排序.第length個數下標為length-1*/
	cout << "快排後的陣列:    ";
	PrintQuickArray(arr, length);

	/*隨機快排的測試,記得把QuickSort裡的Partition換成RandomPartition*/
	/*cout << endl; cout << endl;
	cout << "隨機快排後的陣列:";
	PrintQuickArray(arr, length);*/
	delete[] arr;/*最後要銷燬這個陣列*/
}

實驗結果:

計數排序演算法.h

#pragma once
typedef int dataType;

/*列印陣列*/
void PrintCountArray(dataType arr[], int length);

/*初始化陣列*/
void InitCountArray(dataType arr[], int length);

/*計數排序*/
void CountSort(dataType arr[], int length);

/*計數排序測試函式*/
void TestCountSort();

計數排序演算法.cpp

#include "計數排序.h"
#include <stdlib.h>
#include <time.h>
#include <iostream>
using namespace std;

/*列印陣列*/
void PrintCountArray(dataType arr[], int length)
{
	for (int i = 0; i < length; i++)
	{
		cout << arr[i] << "  ";
		if ((i + 1) % 15 == 0)
			cout << endl;
	}
	cout << endl; cout << endl;
}

/*初始化陣列*/
void InitCountArray(dataType arr[], int length)
{
	srand((unsigned)time(NULL));
	for (int i = 0; i < length; i++)
	{
		arr[i] = rand() % 100 + 1;/*arr[i]在1-100之間*/
	}
}

/*計數排序*/
void CountSort(dataType arr[], int length)
{
	dataType *temp = new dataType[length];/*構造一個臨時陣列*/
	int i, j;
	for (i = 0; i < length; i++)/*這個臨時陣列每個數賦值為0*/
		temp[i] = 0;
	for (i = 0; i < length; i++)
	{
		int count = 0;
		for (j = 0; j < length; j++)/*掃描待排序陣列*/
		{
			if (arr[j] < arr[i])/*統計比arr[i]小的數*/
				count++;
		}
		while (temp[count] != 0)/*如果排的位置已經有了,就往後移(防止兩個或多個數相同帶來錯誤)*/
			count++;
		temp[count] = arr[i];/*把數放到對應位置*/
	}
	for (i = 0; i < length; i++)/*把排好序的陣列賦值給原陣列*/
	{
		arr[i] = temp[i];
	}
	delete[] temp;/*銷燬這個臨時陣列*/
}

/*計數排序測試函式*/
void TestCountSort()
{
	int length;
	cout << "輸入你期望的陣列長度:";
	cin >> length;
	dataType *arr = new dataType[length];
	InitCountArray(arr, length);
	cout << "輸出待排序的陣列:" << endl;
	PrintCountArray(arr, length);
	CountSort(arr, length);
	cout << "輸出排序後的陣列:" << endl;
	PrintCountArray(arr, length);
	delete[] arr;

	cout << endl;
	cout << endl;
	cout << "測試一下有多個數相同的情況:" << endl;
	cout << "這是我們自定義的陣列:" << endl;
	dataType arr2[15] = { 6,6,6,8,8,8,8,20,1,3,5,6,7,15,15 };
	PrintCountArray(arr2, 15);
	CountSort(arr2, 15);
	cout << "輸出排序後的陣列:" << endl;
	PrintCountArray(arr2, 15);
}

實驗結果:

基數排序演算法.h

#pragma once

/*列印陣列*/
void PrintRadixArray(int arr[], int length);

/*初始化陣列*/
void InitRadixArray(int arr[], int length);

/*獲取陣列中最大的數*/
int GetMaxNum(int arr[], int length);

/*獲取數字的位數*/
int GetLoopTimes(int num);

/*進行基數排序*/
void RadixSort(int arr[], int length, int loop);

/*程式執行控制*/
void ControlRadixSort(int arr[], int length);

/*基數排序測試函式*/
void TestRadixSort();

基數排序演算法.cpp

#include "基數排序.h"
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <iostream>
using namespace std;

/*列印陣列*/
void PrintRadixArray(int arr[], int length)
{
	for (int i = 0; i < length; i++)
	{
		cout << arr[i] << "  ";
		if ((i + 1) % 15 == 0)
			cout << endl;
	}
	cout << endl; cout << endl;
}

/*初始化陣列*/
void InitRadixArray(int arr[], int length)
{
	srand((unsigned)time(NULL));
	for (int i = 0; i < length; i++)
	{
		arr[i] = rand() % 1000 + 1;/*arr[i]在1-1000之間*/
	}
}

/*獲取陣列中最大的數*/
int GetMaxNum(int arr[], int length)
{
	int max = 0;
	for (int i = 0; i < length; i++)
	{
		if (max < arr[i])
			max = arr[i];
	}
	return max;
}

/*獲取數字的位數*/
int GetLoopTimes(int num)
{
	int count = 1;
	num /= 10;
	while (num != 0)
	{
		count++;
		num /= 10;
	}
	return count;
}

/*進行基數排序*/
void RadixSort(int arr[], int length, int loop)
{
	/*1、我們建立一批桶子*/
	int buckets[10][10] = { 0 };/*全部賦值為0*/
								/*如何求每一位上的數:
								如256,它的個位=(256/1)%10=6
								它的十位=(256/10)%10=5
								它的百位=(256/100)%10=2
								temp就是其中的1、10、100    */
	int temp = (int)pow(10, loop - 1);
	int i, j, k;
	k = 0;
	for (i = 0; i < length; i++)
	{
		int arrIndex = (arr[i] / temp) % 10;/*2、求出它的個位或十位或百位上的數*/
		for (j = 0; j < 10; j++)
		{
			if (buckets[arrIndex][j] == 0)/*如果這個位置是空的*/
			{
				buckets[arrIndex][j] = arr[i];//3、把它放到arrIndex號桶的正確位置*/
				break;
			}
		}
	}
	/*4、將桶中的數倒回到arr陣列中*/
	for (i = 0; i < 10; i++)
	{
		for (j = 0; j < 10; j++)
		{
			if (buckets[i][j] != 0)
			{
				arr[k] = buckets[i][j];
				buckets[i][j] = 0;
				k++;
			}
		}
	}
}

/*程式執行控制*/
void ControlRadixSort(int arr[], int length)
{
	int max = GetMaxNum(arr, length);
	int loop = GetLoopTimes(max);
	/*對每一位進行桶分配*/
	for (int i = 1; i <= loop; i++)
	{
		RadixSort(arr, length, i);
	}
}

/*基數排序測試函式*/
void TestRadixSort()
{
	int length;
	cout << "輸入你期望的陣列長度:";
	cin >> length;
	int *arr = new int[length];
	InitRadixArray(arr, length);
	cout << "輸出待排序的陣列:" << endl;
	PrintRadixArray(arr, length);
	ControlRadixSort(arr, length);
	cout << "輸出排序後的陣列:" << endl;
	PrintRadixArray(arr, length);
	delete[] arr;
}

實驗結果:

 

 

實驗二 Strassen’s 矩陣乘法和最近點對演算法

1.利用計算機程式設計語言,實現教材第 28.2 章介紹的“Strassen’s 矩陣乘法演算法”,自主
生成兩個 8×8 的矩陣,檢驗演算法的正確性並輸出演算法結果。

2.比較 Strassen’s 矩陣乘法演算法和數學定義的矩陣乘法演算法效率之間的區別,並用直觀的表
達方式把兩種不同矩陣乘法的效率隨矩陣維數的變化趨勢。(沒做)

3.利用計算機程式設計語言,實現教材第 33.4 章介紹的“最近點對演算法”,在擬定的二維空間
點集上檢驗演算法的正確性並輸出演算法結果。

矩陣乘法的Strassen方法.h

#pragma once

template<typename T>
class Strassen_class {
public:
	/*矩陣相加*/
	void ADD(T** MatrixA, T** MatrixB, T** MatrixResult, int MatrixSize);
	/*矩陣相減*/
	void SUB(T** MatrixA, T** MatrixB, T** MatrixResult, int MatrixSize);
	/*樸素演算法實現*/
	void MUL(T** MatrixA, T** MatrixB, T** MatrixResult, int MatrixSize);
	/*A,B矩陣賦值*/
	void FillMatrix(T** MatrixA, T** MatrixB, int length);
	/*列印矩陣*/
	void PrintMatrix(T **MatrixA, int MatrixSize);
	/*Strassen演算法實現*/
	void Strassen(int N, T **MatrixA, T **MatrixB, T **MatrixC);
};

/*測試Strassen函式*/
void TestStrassen();

矩陣乘法的Strassen方法.cpp

#include "stdafx.h"
#include "矩陣乘法的Strassen方法.h"
#include <stdlib.h>
#include <time.h>
#include <iostream>
using namespace std;

/*
c++使用二維陣列,申請動態記憶體方法
申請
int **A;
A = new int *[desired_array_row];
for ( int i = 0; i < desired_array_row; i++)
A[i] = new int [desired_column_size];
釋放
for ( int i = 0; i < your_array_row; i++)
delete [] A[i];
delete[] A;
*/

/*矩陣相加*/
template<typename T>
void Strassen_class<T>::ADD(T** MatrixA, T** MatrixB, T** MatrixResult, int MatrixSize)
{
	for (int i = 0; i < MatrixSize; i++)
		for (int j = 0; j < MatrixSize; j++)
			MatrixResult[i][j] = MatrixA[i][j] + MatrixB[i][j];
}

/*矩陣相減*/
template<typename T>
void Strassen_class<T>::SUB(T** MatrixA, T** MatrixB, T** MatrixResult, int MatrixSize)
{
	for (int i = 0; i < MatrixSize; i++)
		for (int j = 0; j < MatrixSize; j++)
			MatrixResult[i][j] = MatrixA[i][j] - MatrixB[i][j];
}

/*樸素演算法實現*/
template<typename T>
void Strassen_class<T>::MUL(T** MatrixA, T** MatrixB, T** MatrixResult, int MatrixSize)
{
	for (int i = 0; i < MatrixSize; i++)
		for (int j = 0; j < MatrixSize; j++)
		{
			MatrixResult[i][j] = 0;
			for (int k = 0; k < MatrixSize; k++)
			{
				MatrixResult[i][j] = MatrixResult[i][j] + MatrixA[i][k] * MatrixA[k][j];
			}
		}
}

/*A,B矩陣賦值*/
template<typename T>
void Strassen_class<T>::FillMatrix(T** MatrixA, T** MatrixB, int length)
{
	srand((unsigned)time(NULL));
	for(int i=0;i<length;i++)
		for (int j = 0; j < length; j++)
		{
			MatrixA[i][j] = rand() % 5;
			MatrixB[i][j] = rand() % 5;
		}
}

/*列印矩陣*/
template<typename T>
void Strassen_class<T>::PrintMatrix(T **MatrixA, int MatrixSize)
{
	cout << endl;
	for (int i = 0; i < MatrixSize; i++)
	{
		for (int j = 0; j < MatrixSize; j++)
			cout << MatrixA[i][j] << " ";
		cout << endl;
	}
	cout << endl;
}

/*Strassen演算法實現*/
template<typename T>
void Strassen_class<T>::Strassen(int N, T **MatrixA, T **MatrixB, T **MatrixC)
{
	int halfSize = N / 2;
	int newSize = N / 2;
	int i, j;

	/*分治門檻,小於這個值時不再進行遞迴計算,而是採用常規矩陣計算方法*/
	if (N <= 64)
		MUL(MatrixA, MatrixB, MatrixC, N);
	else
	{
		T** A11;
		T** A12;
		T** A21;
		T** A22;

		T** B11;
		T** B12;
		T** B21;
		T** B22;

		T** C11;
		T** C12;
		T** C21;
		T** C22;

		T** P1;
		T** P2;
		T** P3;
		T** P4;
		T** P5;
		T** P6;
		T** P7;
		T** aResult;
		T** bResult;

		A11 = new T *[newSize];
		A12 = new T *[newSize];
		A21 = new T *[newSize];
		A22 = new T *[newSize];

		B11 = new T *[newSize];
		B12 = new T *[newSize];
		B21 = new T *[newSize];
		B22 = new T *[newSize];

		C11 = new T *[newSize];
		C12 = new T *[newSize];
		C21 = new T *[newSize];
		C22 = new T *[newSize];

		P1 = new T *[newSize];
		P2 = new T *[newSize];
		P3 = new T *[newSize];
		P4 = new T *[newSize];
		P5 = new T *[newSize];
		P6 = new T *[newSize];
		P7 = new T *[newSize];

		aResult = new T *[newSize];
		bResult = new T *[newSize];

		int newLength = newSize;

		/*把一維陣列二維化*/
		for (i = 0; i < newSize; i++)
		{
			A11[i] = new T [newSize];
			A12[i] = new T [newSize];
			A21[i] = new T [newSize];
			A22[i] = new T [newSize];

			B11[i] = new T [newSize];
			B12[i] = new T [newSize];
			B21[i] = new T [newSize];
			B22[i] = new T [newSize];

			C11[i] = new T [newSize];
			C12[i] = new T [newSize];
			C21[i] = new T [newSize];
			C22[i] = new T [newSize];

			P1[i] = new T [newSize];
			P2[i] = new T [newSize];
			P3[i] = new T [newSize];
			P4[i] = new T [newSize];
			P5[i] = new T [newSize];
			P6[i] = new T [newSize];
			P7[i] = new T [newSize];

			aResult[i] = new T [newSize];
			bResult[i] = new T [newSize];
		}

		/*將輸入矩陣分解成4個子矩陣*/
		for (i = 0; i < N / 2; i++)
		{
			for (j = 0; j < N / 2; j++)
			{
				A11[i][j] = MatrixA[i][j];
				A12[i][j] = MatrixA[i][j + N / 2];
				A21[i][j] = MatrixA[i + N / 2][j];
				A22[i][j] = MatrixA[i + N / 2][j + N / 2];

				B11[i][j] = MatrixB[i][j];
				B12[i][j] = MatrixB[i][j + N / 2];
				B21[i][j] = MatrixB[i + N / 2][j];
				B22[i][j] = MatrixB[i + N / 2][j + N / 2];
			}
		}

		/*計算P1-P7*/
		/*P1=A11*(B11-B22)*/
		SUB(B11, B22, bResult, halfSize);
		Strassen(halfSize, A11, bResult, P1);

		/*P2=(A11+A12)*B22*/
		ADD(A11, A12, aResult, halfSize);
		Strassen(halfSize, aResult, B22, P2);

		/*P3=(A21+A22)*B11*/
		ADD(A21, A22, aResult, halfSize);
		Strassen(halfSize, aResult, B11, P3);

		/*P4=A22*(B21-B11)*/
		SUB(B11, B11, bResult, halfSize);
		Strassen(halfSize, A22, bResult, P4);

		/*P5=(A11+A22)*(B11+B22)*/
		ADD(A11, A22, aResult, halfSize);
		ADD(B11, B22, bResult, halfSize);
		Strassen(halfSize, aResult, bResult, P5);

		/*P6=(A12-A22)*(B21+B22)*/
		SUB(A12, A22, aResult, halfSize);
		ADD(B21, B22, bResult, halfSize);
		Strassen(halfSize, aResult, bResult, P6);

		/*P7=(A11-A21)*(B11+B12)*/
		SUB(A11, A21, aResult, halfSize);
		ADD(B11, B12, bResult, halfSize);
		Strassen(halfSize, aResult, bResult, P7);

		/*計算C11、C12、C21、C22*/
		/*C11=P5+P4-P2+P6*/
		ADD(P5, P4, aResult, halfSize);
		SUB(P2, P6, bResult, halfSize);
		SUB(aResult, bResult, C11, halfSize);

		/*C12=P1+P2*/
		ADD(P1, P2, C12, halfSize);

		/*C21=P3+P4*/
		ADD(P3, P4, C21, halfSize);

		/*C22=P5+P1-P3-P7*/
		ADD(P5, P1, aResult, halfSize);
		ADD(P3, P7, bResult, halfSize);
		SUB(aResult, bResult, C22, halfSize);

		/*組合小矩陣到一個大矩陣*/
		for (int i = 0; i < N / 2; i++)
		{
			for (int j = 0; j < N / 2; j++)
			{
				MatrixC[i][j] = C11[i][j];
				MatrixC[i][j + N / 2] = C12[i][j];
				MatrixC[i + N / 2][j] = C21[i][j];
				MatrixC[i + N / 2][j + N / 2] = C22[i][j];
			}
		}

		/*釋放矩陣記憶體空間*/
		for (int i = 0; i < newLength; i++)
		{
			delete[] A11[i]; delete[] A12[i]; delete[] A21[i]; delete[] A22[i];
			delete[] B11[i]; delete[] B12[i]; delete[] B21[i]; delete[] B22[i];
			delete[] C11[i]; delete[] C12[i]; delete[] C21[i]; delete[] C22[i];
			
			delete[] P1[i]; delete[] P2[i]; delete[] P3[i]; delete[] P4[i];
			delete[] P5[i]; delete[] P6[i]; delete[] P7[i];
			delete[] aResult[i]; delete[] bResult[i];
		}
		delete[] A11; delete[] A12; delete[] A21; delete[] A22;
		delete[] B11; delete[] B12; delete[] B21; delete[] B22;
		delete[] C11; delete[] C12; delete[] C21; delete[] C22;
		delete[] P1; delete[] P2; delete[] P3; delete[] P4; delete[] P5;
		delete[] P6; delete[] P7;
		delete[] aResult;
		delete[] bResult;
	}

}

/*測試Strassen函式*/
void TestStrassen()
{
	/*定義Strassen_class類物件*/
	Strassen_class<int> stra;

	int MatrixSize = 0;

	/*存放矩陣A*/
	int** MatrixA;    
	/*存放矩陣B*/
	int** MatrixB;    
	/*存放結果矩陣*/
	int** MatrixC;

	clock_t startTime_For_Normal_Multipilication;
	clock_t endTime_For_Normal_Multipilication;

	clock_t startTime_For_Strassen;
	clock_t endTime_For_Strassen;

	srand((unsigned)time(NULL));

	cout << "\n請輸入矩陣大小(必須是2的冪指數值(例如:32,64,512,..): ";
	cin >> MatrixSize;

	int N = MatrixSize;//for readiblity.

					   //申請記憶體
	MatrixA = new int *[MatrixSize];
	MatrixB = new int *[MatrixSize];
	MatrixC = new int *[MatrixSize];

	for (int i = 0; i < MatrixSize; i++)
	{
		MatrixA[i] = new int[MatrixSize];
		MatrixB[i] = new int[MatrixSize];
		MatrixC[i] = new int[MatrixSize];
	}

	stra.FillMatrix(MatrixA, MatrixB, MatrixSize);  //矩陣賦值

	/*暴力演算法測試*/
	cout << "樸素矩陣演算法開始時鐘:  " << (startTime_For_Normal_Multipilication = clock());
	stra.MUL(MatrixA, MatrixB, MatrixC, MatrixSize);//樸素矩陣相乘演算法 T(n) = O(n^3)
	cout << "\n樸素矩陣演算法結束時鐘: " << (endTime_For_Normal_Multipilication = clock());
	cout << "\n矩陣運算結果... \n";
	stra.PrintMatrix(MatrixC, MatrixSize);
	/*Strassen演算法測試*/
	cout << "\nStrassen演算法開始時鐘: " << (startTime_For_Strassen = clock());
	stra.Strassen(N, MatrixA, MatrixB, MatrixC); //strassen矩陣相乘演算法
	cout << "\nStrassen演算法結束時鐘: " << (endTime_For_Strassen = clock());
	cout << "\n矩陣運算結果... \n";
	stra.PrintMatrix(MatrixC, MatrixSize);

	cout << "矩陣大小 " << MatrixSize;
	cout << "\n樸素矩陣演算法: " 
		<< (endTime_For_Normal_Multipilication - startTime_For_Normal_Multipilication) 
		<< " Clocks.." 
		<< (endTime_For_Normal_Multipilication - startTime_For_Normal_Multipilication) / CLOCKS_PER_SEC 
		<< " Sec";
	cout << "\nStrassen演算法:" 
		<< (endTime_For_Strassen - startTime_For_Strassen) 
		<< " Clocks.." 
		<< (endTime_For_Strassen - startTime_For_Strassen) / CLOCKS_PER_SEC 
		<< " Sec\n";
}

執行結果

最近點對問題.h

#pragma once

#define NO_DISTANCE 1000000

/*定義二維點Point*/
typedef struct Point
{
	/*x,y分別為二維點的橫、縱座標,範圍[-100,100]*/
	float x, y;
}Point;

/*用隨機函式對點陣列points中的二維陣列進行初始化*/
void SetPoints(Point *points, int length);

/*平面內任意兩點距離公式*/
float Distance(Point a, Point b);

/*暴力解法*/
float SimplePair(Point points[], int length, Point &a, Point &b);

/*自定義排序規則:依照結構體成員中x變數的升序排序*/
bool CmpX(Point a, Point b);

/*求出最近點對,記錄在a、b中,並返回最短距離*/
float ClosestPair(Point points[], int length, Point &a, Point &b);

/*測試函式*/
void TestClosePair();

最近點對問題.cpp

#include "stdafx.h"
#include "最近點對問題.h"
#include <iostream>
#include <ctime>
#include <cmath>
#include <algorithm>
using namespace std;

/*用隨機函式對點陣列points中的二維陣列進行初始化*/
void SetPoints(Point *points, int length)
{
	srand((unsigned)time(NULL));
	for (int i = 0; i < length; i++)
	{
		points[i].x = (rand() % 20000) / 100.0 - 100;
		points[i].y = (rand() % 20000) / 100.0 - 100;
	}
}

/*平面內任意兩點距離公式*/
float Distance(Point a, Point b)
{
	return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}

/*暴力解法*/
float SimplePair(Point points[], int length, Point &a, Point &b)
{
	/*記錄集合points中最近兩點的距離*/
	float distance=1000000.0;
	/*臨時記錄最短距離*/
	float temp=0;
	for(int i=0;i<length;i++)
		for (int j = i+1; j < length; j++)
		{
			temp = Distance(points[i], points[j]);
			if (temp < distance)
			{
				distance = temp;
				a = points[i];
				b = points[j];
			}
		}
	return distance;
}

/*自定義排序規則:依照結構體成員中x變數的升序排序*/
bool CmpX(Point a, Point b)
{
	return a.x < b.x;
}

/*求出最近點對,記錄在a、b中,並返回最短距離*/
float ClosestPair(Point points[], int length, Point &a, Point &b)
{
	/*記錄集合points中最近兩點的距離*/
	float distance;
	/*記錄分割後兩個子集中各自最小點對的距離*/
	float d1, d2;
	/*用於控制for迴圈的變數*/
	int i, j, k;
	/*儲存分割中兩個子集中最小點對*/
	Point a1, b1, a2, b2;

	/*若只有一個點,定義為最大距離,表示不可達*/
	if (length < 2)return NO_DISTANCE;
	if (length == 2)
	{
		a = points[0];
		b = points[1];
		distance = Distance(a, b);
	}
	else
	{
		/*開闢兩個子集*/
		Point *pts1 = new Point[length/2+1];
		Point *pts2 = new Point[length/2+1];

		/*sort:對給定區間所有元素進行排序*/
		/*Sort函式有三個引數:
			(1)第一個是要排序的陣列的起始地址。
			(2)第二個是結束的地址(最後一位要排序的地址的下一地址)
			(3)第三個引數是排序的方法,可以是從大到小也可是從小到大,還可以不寫第三個引數,此時預設的排序方法是從小到大排序。*/
		/*呼叫algorithm庫中的sort函式對points進行升序排序*/
		sort(points, points + length, CmpX);

		/*排完序後的中間下標值,即中位數*/
		float mid = points[(length - 1) / 2].x;

		/*把左半邊的值賦值給pts1*/
		for (size_t i = 0; i < length / 2; i++)
			pts1[i] = points[i];
		/*把右半邊的值賦值給pts2*/
		for (int j = 0, i = length / 2; i < length; i++)
			pts2[j++] = points[i];

		/*分治求解左半邊子集的最遠點*/
		d1 = ClosestPair(pts1, length / 2, a1, b1);

		/*分治求解右半邊子集的最遠點*/
		d2 = ClosestPair(pts2, length-length / 2, a2, b2);
		if (d1 < d2) 
		{
			distance = d1;
			a = a1;
			b = b1;
		}
		else
		{
			distance = d2;
			a = a2;
			b = b2;
		}

		/*求跨越分割線的最近點對*/
		Point *pts3 = new Point[length];
		for (i = 0, k = 0; i < length; i++)
			if (abs(points[i].x - mid) <= distance)
				pts3[k++] = points[i];
		for (i = 0; i < k; i++)
			for (j = i + 1; j <= i + 7 && j < k; j++)
			{
				if (Distance(pts3[i], pts3[j]) < distance)
				{
					distance = Distance(pts3[i], pts3[j]);
					a = pts3[i];
					b = pts3[j];
				}
			}
	}
	return distance;
}

/*測試函式*/
void TestClosePair()
{
	/*記錄隨機生成的點對數*/
	int amount;
	Point a, b;
	Point A, B;
	float distance;
	float distance2;/*暴力解法*/

	cout << "請輸入二維點對個數:";
	cin >> amount;

	if (amount < 2)
		cout << "請輸入大於等於2的點個數!" << endl;
	else
	{
		cout << endl << "隨機生成的" << amount << "個二維點對如下:" << endl;
		Point *points = new Point[amount];
		SetPoints(points, amount);

		for (int i = 0; i < amount; i++)
		{
			printf("(%.2f,%.2f) ", points[i].x, points[i].y);
			if (0 == (i + 1) % 5)
				cout << endl;
		}

		distance = ClosestPair(points, amount, a, b);
		distance2 = SimplePair(points, amount, A, B);
		
		cout << endl << "按橫座標排序後的點對如下:" << endl;
		for (int i = 0; i < amount; i++)
		{
			printf("(%.2f,%.2f) ", points[i].x, points[i].y);
			if (0 == (i + 1) % 5)
				cout << endl;
		}

		cout << endl;
		printf("最近點對為:(%.2f,%.2f)和(%.2f,%.2f),\n", a.x, a.y, b.x, b.y);
		cout << "它們之間的距離為:" << distance << endl;
		cout << endl;
		printf("暴力解法最近點對為:(%.2f,%.2f)和(%.2f,%.2f),\n", A.x, A.y, B.x, B.y);
		cout << "暴力解法的距離為:" << distance2 << endl;
	}
}

執行結果

實驗三:作業排程和最長共同子序列算

1.描述並實現動態規劃的作業排程演算法,並顯示下圖的排程結果

2.描述並實現最長共同子序列動態規 劃 算 法 , 並 顯 示 S1=
ACCGGTCGAGATGCAG,S2 = GTCGTTCGGAATGCAT 的最長共同子序列。

任務一:

裝配線排程問題.h

#pragma once
/*  7   9   3	4	8
  2   2	  3   1   3    3
0						  0
  4   2   1   2   2    6
    8	5	6	4	5
  */  

/*最快的路線*/
void FastWay();

/*列印路線*/
void PrintStations();

裝配線排程問題.cpp

#include "stdafx.h"
#include "裝配線排程問題.h"
#include <stdio.h>
/*
f1[j]=   e1+a1,1   ,j=1
         min( f[1][j-1]+a[1][j] , f[2][j-1]+t[2][j-1]+a[1][j] )
f2[j]=   e2+a2,1   ,j=1
		 min( f[2][j-1]+a[2][j] , f[1][j-1]+t[1][j-1]+a[2][j] )
*/
int f_star, l_star;
int f[3][6];
int l[3][6];
int a[3][6] = { { 0,0,0,0,0,0 },{ 0,7,9,3,4,8 },{ 0,8,5,6,4,5 } };/*第一條線和第二條線*/
int t[3][5] = { { 0,0,0,0,0 },{ 0,2,3,1,3 },{ 0,2,1,2,2 } };/*第一個緩衝和第二個緩衝*/
int e[3] = { 0,2,4 };
int x[3] = { 0,3,6 };

/*最快的路線*/
void FastWay()
{
	int j;
	f[1][1] = e[1] + a[1][1];
	f[2][1] = e[2] + a[2][1];
	for (j = 2; j < 6; j++)
	{
		/*遍歷上面的結點*/
		if (f[1][j - 1] + a[1][j] <= f[2][j - 1] + t[2][j - 1] + a[1][j])/*往上面直接走比較快*/
		{
			f[1][j] = f[1][j - 1] + a[1][j];
			l[1][j] = 1;/*走第一條路*/
		}
		else/*往下面直接走比較快*/
		{
			f[1][j] = f[2][j - 1] + t[2][j - 1] + a[1][j];
			l[1][j] = 2;/*走第2條路*/
		}
		/*遍歷下面的結點*/
		if (f[2][j - 1] + a[2][j] <= f[1][j - 1] + t[1][j - 1] + a[2][j])
		{
			f[2][j] = f[2][j - 1] + a[2][j];
			l[2][j] = 2;
		}
		else
		{
			f[2][j] = f[1][j - 1] + t[1][j - 1] + a[2][j];
			l[2][j] = 1;
		}
	}
	/*走到最後如果上面的路比下面的路短*/
	if (f[1][5] + x[1] <= f[2][5] + x[2])
	{
		f_star = f[1][5] + x[1];
		l_star = 1;
	}
	else
	{
		f_star = f[2][5] + x[2];
		l_star = 2;
	}
}

/*列印路線*/
void PrintStations()
{
	FastWay();
	int j;
	int i = l_star;/*決定最後是哪條路*/
	for (j = 2; j < 6; j++)
	{
		i = l[i][j];
		printf("line %d,station %d\n", i, j-1);
	}
	printf("line %d,station %d\n", i, 5);
	printf("最短為:%d",f_star);
}

執行結果

任務二:

最長共同子序列.h

#pragma once
#include <iostream>
#include <vector>
using namespace std;

/*求解最長共同子序列*/
void LCS(string A, string B);

/*測試函式*/
void TestLCS();

最長共同子序列.cpp

#include "stdafx.h"
#include "最長共同子序列.h"

/*
C[i][j]=    0								 i=0 或 j=0
            C[i-1][j-1]+1                    x[i]= y[j]
			max( C[i][j-1],C[i-1][j] )       x[i]≠y[j]
*/

/*求解最長共同子序列*/
void  LCS(string A, string B)
{
	int i;
	int j;
	int **C;
	C = new int *[A.size() +1];/*A.size()=16*/
	for (int k = 0; k <= A.size(); k++)
		C[k] = new int[B.size() +1];
	/*初始化C[0][j]=0*/
	for (i = 0; i <= A.size(); i++)
	for (j = 0; j <= B.size(); j++)
	{
		C[i][j] = 0;
	}
	for (i = 1; i <= A.size(); i++)
	{
		for (j = 1; j <= B.size(); j++)
		{
			if (A[i-1] == B[j-1])
			{
				C[i][j] = C[i - 1][j - 1] + 1;
			}
			else if (C[i][j - 1] >= C[i - 1][j])
			{
				C[i][j] = C[i][j - 1];
			}
			else
			{
				C[i][j] = C[i - 1][j];
			}
		}
	}
	cout << "共同子序列的長度為:";
	cout<< C[A.size()][ B.size()];

	int aPos = A.size();
	int bPos = B.size();
	int commonLen = C[aPos][bPos];//最後一個元素的值就是最長共同子序列的長度
	int k = commonLen;
	string common;//共同子序列
	common.resize(commonLen);
	//從兩序列最後一個字元開始往前走,有一個字串Over就結束
	while (aPos && bPos)
	{
		//兩序列最後一個元素相等,則同時往前走一步
		if (C[aPos][bPos] == C[aPos - 1][bPos] + 1)
		{
			common[--k] = A[--aPos];
			--bPos;
		}
		else if (C[aPos - 1][bPos] >= C[aPos][bPos - 1])
		{
			--aPos;/*行*/
		}
		else
		{
			--bPos;/*列*/
		}
	}
	cout << endl;
	cout << "子串為:";
	for (int i = 0; i < commonLen; i++)
	{
		cout << common[i];
	}
	cout << endl;
}

void TestLCS()
{
	string A = "ACCGGTCGAGATGCAG";
	string B = "GTCGTTCGGAATGCAT";
	LCS(A, B);
}

執行結果

實驗四:單源最短路徑和全點對最短路徑演算法

1.描述並實現單源最短路徑演算法,顯示在下圖上的運算結果

2.描述並實現全點對最短路徑演算法,顯示在下圖上的運算結果

任務一

單源最短路徑.h

#pragma once
#define INFINITY 100/*無窮大*/
#define DOTNUMBER 5/*點數*/
#define LINENUMBER 10/*邊數*/

struct Line/*一條邊*/
{
	int start;/*起點*/
	int end;/*終點*/
	int weight;/*權重*/
};

struct Vertex
{
	int smallCost;/*最小開銷*/
	int father;/*父結點*/
};

/*v個結點,s為起點,初始化*/
void InitSingleSource(int s);

/*鬆弛函式*/
void RelaxSingleSource(int s);

/*Bellman-Ford演算法*/
bool Bellman_Ford(int s);

/*列印*/
void PrintSingleSource(int src, int des);

void TestSingleSource();

單源最短路徑.cpp

#include "stdafx.h"
#include "單源最短路徑.h"
#include <iostream>
#include <stdio.h>
using namespace std;

//#define INFINITY 100/*無窮大*/
//#define DOTNUMBER 5/*點數*/
//#define LINENUMBER 10/*邊數*/


struct Vertex vertex[DOTNUMBER];/*5個節點*/
struct Line line[LINENUMBER];/*10條邊*/

/*s為起點,初始化*/
void InitSingleSource(int s)
{
	for (int i = 0; i < DOTNUMBER; i++)
	{
		vertex[i].smallCost = INFINITY;/*初始化為無窮大*/
		vertex[i].father = -1;/*初始化父結點為NULL*/
	}
	vertex[s].smallCost = 0;/*初始化起點權重為0*/
}

/*鬆弛函式*/
void RelaxSingleSource(int s)
{
	/*If v.d>u.d + w(u, v)
		v.d = u.d + w(u, v)
		v.π = u*/
	int i;

	for (i = 0; i < DOTNUMBER; i++) {
		for (int j = 0; j <LINENUMBER; j++) {//arr是邊集,e是邊數,V是點集
			int start = line[j].start;/*邊的起點x*/
			int end = line[j].end;/*邊的終點y*/
			int weight = line[j].weight;/*邊的權重z*/
			/*如果邊的起點≠無窮大 且 邊的終點的最小開銷>邊的起點的最小開銷+邊的權重*/
			if (vertex[start].smallCost != INT_MAX && vertex[end].smallCost>vertex[start].smallCost + weight)
			{
				/*邊的終點的最小開銷=邊的起點的最小開銷+邊的權重*/
				vertex[end].smallCost = vertex[start].smallCost + weight;
				vertex[end].father = start;/*邊的終點的父結點=邊的起點*/
			}
		}
	}
}

/*Bellman-Ford演算法*/
bool Bellman_Ford(int s)
{
	RelaxSingleSource(s);
	int i;
	for (i = 0; i <= LINENUMBER; i++) /*遍歷每一條邊*/
	{
		int start = line[i].start;/*邊的起點x*/
		int end = line[i].end;/*邊的終點y*/
		int weight = line[i].weight;/*邊的權重z*/
		/*如果邊的起點的最小開銷≠無窮 且 邊的終點的最小開銷>邊的起點的最小開銷+權重*/
		if (vertex[start].smallCost != INT_MAX && vertex[end].smallCost>vertex[start].smallCost + weight)
			return false;/*表示有負的環路*/
	}
	return true;
}

/*列印*/
void PrintSingleSource(int src,int des)
{
	if (des == src)
	{
		switch (des)
		{
		case 0:cout << 's'; break;
		case 1:cout << 't'; break;
		case 2:cout << 'x'; break;
		case 3:cout << 'y'; break;
		case 4:cout << 'z'; break;
		default:
			break;
		}
	}
	else
	{
			PrintSingleSource(src, vertex[des].father);
			switch (des)
			{
			case 0:cout << "-->" << 's'; break;
			case 1:cout << "-->" << 't'; break;
			case 2:cout << "-->" << 'x'; break;
			case 3:cout << "-->" << 'y'; break;
			case 4:cout << "-->" << 'z'; break;
			default:
				break;
			}
	}
}

void TestSingleSource()
{
	InitSingleSource(0);/*初始化*/
	int s = 0; int i;
	
	line[0] = { 0,1,6 };
	line[1] = { 0,3,7 };
	line[2] = { 1,2,5 };
	line[3] = { 2,1,-2 };
	line[4] = { 1,3,8 };
	line[5] = { 3,2,-3 };
	line[6] = { 3,4,9 };
	line[7] = { 4,2,7 };
	line[8] = { 1,4,-4 };
	line[9] = { 4,0,2 };


	if (Bellman_Ford(s))
		PrintSingleSource(0, 4);
	else
		cout << "!empty" << endl;
}

執行結果

任務二

點對最短路徑.h

#pragma once

#include <iostream>
#include <vector>
#define POINTSIZE 5/*點的個數*/

using namespace std;


/*初始化路徑*/
void InitPointPair(vector<vector<int>> &array, vector<vector<int>> &Path);

/*Floyd演算法*/
void Floyd_Warshall(vector<vector<int>> &Distance, vector<vector<int>> &Path, vector<vector<int>> &Array);/*返回一個二維陣列指標*/

/*顯示計算結果*/
void ShowResult(vector<vector<int>> &Distance, vector<vector<int>> &Path);

/*列印矩陣*/
void ShowVector(vector<vector<int>> &vec);



void test();

點對最短路徑.cpp

#include "stdafx.h"
#include "點對最短路徑.h"

/*初始化路徑*/
void InitPointPair(vector<vector<int>> &array, vector<vector<int>> &Path)
{
	for (int i = 0; i < POINTSIZE; i++)
	{
		for (int j = 0; j < POINTSIZE; j++)
		{
			if (array[i][j] < INT_MAX)
				Path[i][j]=j;
		}
	}
}

/*Floyd演算法*/
void Floyd_Warshall(vector<vector<int>> &Distance, vector<vector<int>> &Path, vector<vector<int>> &Array)/*返回一個二維陣列指標*/
{
	Distance = Array;
	for (int k = 0; k < POINTSIZE; k++)
	{
		for (int i = 0; i < POINTSIZE; i++)
		{
			for (int j = 0; j < POINTSIZE; j++)
			{
				if (Distance[i][j] > Distance[i][k] + Distance[k][j])
				{
					Distance[i][j] = Distance[i][k] + Distance[k][j];	//發現了更短的距離,取代前者
					Path[i][j] = Path[i][k];		//更新路徑
				}
			}
		}
	}
}

/*顯示計算結果*/
void ShowResult(vector<vector<int>> &Distance, vector<vector<int>> &Path)
{
	for (int i = 0; i < POINTSIZE; i++)
	{
		for (int j = 0; j < POINTSIZE; j++)
		{
			printf("結點%d到結點%d的最短路徑是為%d,\t", i, j, Distance[i][j]);
			int k = Path[i][j];
			if (k == -1)
				cout << "路徑不存在!" << endl;
			else
			{
				/*列印i->j的路徑*/
				cout << "("<<i;
				while (k != j)
				{
					cout << "->" << k;
					k = Path[k][j];
				}
				cout << "->" << j<<")"<<endl;
			}
		}
	}
}

/*列印矩陣*/
void ShowVector(vector<vector<int>> &vec)
{
	for (int i = 0; i < POINTSIZE; i++)
	{
		for (int j = 0; j < POINTSIZE; j++)
		{
			if (vec[i][j] < INT_MAX / 2)
				cout << vec[i][j] << "  ";
			else
				cout << "∞" << "  ";
		}
		cout << endl;
	}
}

void test()
{
	//vector<vector<int> > Array;/*鄰接矩陣*/
	vector<vector<int> > Path;/*計算路徑*/
	vector<vector<int> > Distance;/*計算距離*/
	Path = vector<vector<int> >(POINTSIZE, vector<int>(POINTSIZE, -1));/*陣列元素的初始值為-1*/
	vector<vector<int> > Array(5, vector<int>(5,INT_MAX / 2));/*vector<int>(5, INT_MAX / 2)*/
	Array[0][1] = 3; Array[0][2] = 8; Array[0][4] = -4;
	Array[1][3] = 1;	Array[1][4] = 7;
	Array[2][1] = 4;
	Array[3][0] = 2;	Array[3][2] = -5;
	Array[4][3] = 6;
	for (int i = 0; i <POINTSIZE; ++i)	Array[i][i] = 0;/*自己到自己的距離=0*/
	InitPointPair(Array, Path);/*初始化*/
	cout << "初始化的鄰接矩陣為:" << endl;
	ShowVector(Array);
	cout << endl << "Floyd計算後的鄰接矩陣為:" << endl;
	Floyd_Warshall(Distance, Path, Array);
	ShowVector(Distance);
	cout << "每兩個結點之間的路徑:" << endl;
	ShowResult(Distance, Path);

	/*vector<vector<int>> W(5, vector<int>(5, INT_MAX / 2));
	W[0][1] = 3;	W[0][2] = 8;	W[0][4] = -4;
	W[1][3] = 1;	W[1][4] = 7;
	W[2][1] = 4;
	W[3][0] = 2;	W[3][2] = -5;
	W[4][3] = 6;
	for (int i = 0; i < W.size(); ++i)	W[i][i] = 0;
	Floyd_Warshall fw(W);
	cout << "初始化的鄰接矩陣為:" << endl;
	fw.show_vec(W);
	cout << endl << "Floyd計算後的鄰接矩陣為:" << endl;
	fw.show_vec(fw.floyd_warshall());
	cout << "每兩個結點之間的路徑:" << endl;
	fw.show_path();

	vector<vector<int>>*/
}


執行結果

好了,全部結束了,這邊並不全是我本人自己寫的,很多都是借鑑網上一些大觸的作品,感謝無私奉獻的各位大觸!

最後,希望你有所收穫。