《算法导论》上机总结

突然想到把所有的上机都总结一下。如果有错误还请不吝斧正。

目录

实验一 排序算法

实验二 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>>*/
}


运行结果

好了,全部结束了,这边并不全是我本人自己写的,很多都是借鉴网上一些大触的作品,感谢无私奉献的各位大触!

最后,希望你有所收获。

猜你喜欢

转载自blog.csdn.net/weixin_40851250/article/details/84063262
今日推荐