《演算法導論》上機總結
突然想到把所有的上機都總結一下。如果有錯誤還請不吝斧正。
目錄
首先說明一下程式碼格式:我這邊所有的東西基本都寫到 了一起。就像這樣:
然後執行的時候只要把我程式碼中的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>>*/
}
執行結果
好了,全部結束了,這邊並不全是我本人自己寫的,很多都是借鑑網上一些大觸的作品,感謝無私奉獻的各位大觸!
最後,希望你有所收穫。