实验4:递归与分治策略的应用

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

课程实验报告

运行到一定规模:

快速排序:

运行到一定规模:堆排序:

运行到一定规模:

矩阵乘法:

1朴素算法:

2Strassen矩阵乘算法一定规模后:

横坐标计算规模:1:8129 2:65536 3:131072 4:262144 5:1048576

随着输入规模的增大,通过三种算法的时间记录做成折线图观察不难发现,在初期,三种算法所用时间几乎相等,随着输入规模的不断增大,堆排序和快速排序仍然能够保持相对较小的增长,而并归排序所用时间复杂度开始大幅度增加。

快速排序果然是快,数据越大优势越明显,并且实现上也较为简单。理论上它的平均时间和归并排序,堆排序都是一样的(在最坏情况还还不如它们),都是O(nlog2n),但实际运行来看比它们两者的速度都快一倍以上。COOL!

合并排序需要额外相同规模的数组,空间复杂度为O(n)。从具体实现来看,这只是一种理论上的优秀算法,想法比较简单直接,但实现上比quicksort 复杂,运行时间也差,在数据很大的时候运行时间是heapsort的两倍,更不用说quicksort

了。

堆排序利用了二分树的结构,将时间复杂度降到O(nlog2n),理论上和实现上表现都不错,并且发现在数据量是10 000 000时,甚至优于快排,可能是运行时数据的问题。

对于strassen 算法对其时间复杂度分析:T(n)=7T(n/2)+O(n);而朴素算法的时间复杂度为n的三次方。

随着数据增大,也出现乘方级别的时间复杂度差距。

附录//头文件

#include

#include

#include

#include

#include

#define PARENT(i) (i/2) //几个较简单函数

#define LEFT(i) (2*i+1)

#define RIGHT(i) (2*i+2)

using namespace std;

//定义所需要变量等

#define MAX 100000

int a[MAX]; //数组存储原始顺序

int temp[MAX]; //临时数组存储临时排序值

int num; //计算统计逆序对数

int N = 2; //数据规模

clock_t begintimes, endtimes; //clock_t为clock()函数返回的变量类型double duration; //运行时间计算

int heapsize; //堆长度

//随机生成数函数

int number(){

int a;

a = rand() % 10000 + 1; //随机生成1到一万之间的整数

return a;

}

//初始化函数对数组a[]初始化。

void init(){

memset(temp,0, MAX * sizeof(int)); //临时数组清零

for (int i = 0; i < N; i++){ //新数组赋值

a[i] = number();

}

return;

}

//单次并归挑选

void Merge(int left, int mid, int right) //需要三个参数,将原来数组分割

{

int i = left, j = mid + 1, n = 0, length = right - left;//i开始为左半部分最左边,j为右半部分最左边

while (i <= mid && j <= right){ //未超限进行循环填数

if (a[i]>a[j]){ //左边比右边大

temp[n++] = a[j++];

num += mid - i + 1; //从i到mid都比a[j]大

}

else{

temp[n++] = a[i++];

}

}

if (i>mid){ //左边全部填满了,填右边

while (j <= right){

temp[n++] = a[j++];

}

}

else{ //右边填满,填左边

while (i <= mid){

temp[n++] = a[i++];

}

}

for (int k = 0; k <= length; k++){ //最后临时数组赋值到原数组

a[left + k] = temp[k];

}

//递归进行并归排序

void MergeSort(int left, int right)

{

if (left

int mid = (left + right) / 2;

MergeSort(left, mid);

MergeSort(mid + 1, right);

Merge(left, mid, right);

}

}

//快速排序一次

int Partition(int left, int right)

{

int i = left - 1;

for (int j = left; j <= right - 1; j++){

if (a[j] < a[right]){ //把right作为轴

i++; //这个i坐标左边的值是比a[right]小的

swap(a[i], a[j]); //交换

}

}

swap(a[i + 1], a[right]); //最后把i+1和right交换,这样轴就是i+1了必须是保证i+1上当初就是作为标杆的a[right]啊。

return i + 1;

}

//递归进行快排整体

void QuickSort(int left, int right){

if (left

int q = Partition(left, right);

QuickSort(left, q - 1);

QuickSort(q + 1, right);

}

}

//堆排序,函数太多,新建一个命名空间

namespace MySort{

template //堆排序的大顶堆优化(找数)

void Max_Heapify(T*arr, int i, size_t heapSize){

//从元素A[i]、A[LEFT(i)]、A[RIGHT(i)]中找出最大的,并将其下标保存在Largest中

//size_t heapSize = sizeof(arr) / sizeof(*(arr)); 也就是数量n

相关文档
最新文档