算法实验报告2
算法分析与设计实验报告
实验二 几种排序算法的实验性能比较
- 实验目的
实现插入排序(Insertion Sort,IS),自顶向下归并排序(Top-down Mergesort,TDM),自底向上归并排序(Bottom-up Mergesort,BUM),随机快速排序(Random Quicksort,RQ),Dijkstra 3-路划分快速排序(Quicksort with Dijkstra 3-way Partition,QD3P)。在你的
计算机上针对不同输入规模数据进行实验,对比上述排序算法的时间及空间占用性能。要求对于每次输入运行 10 次,记录每次时间/空间占用,取平均值。
- 实验环境
Java8 Eclipse algs4.jar包
- 实验内容
实现插入排序(Insertion Sort,IS),自顶向下归并排序(Top-down Mergesort,TDM),自底向上归并排序(Bottom-up Mergesort,BUM),随机快速排序(Random Quicksort,RQ),Dijkstra 3-路划分快速排序(Quicksort with Dijkstra 3-way Partition,QD3P)。在你的
计算机上针对不同输入规模数据进行实验,对比上述排序算法的时间及空间占用性能。要求对于每次输入运行 10 次,记录每次时间/空间占用,取平均值。
- 实验程序设计
(1)插入排序实现
package second_homework;
public class Is {
private static void exch(Comparable a[],int x,int y)
{
Comparable temp = a[x];
a[x] = a[y];
a[y] = temp;
}
public static void sort(Comparable a[])
{
int N = a.length;
for(int i=0;i<N;i++)
{
for(int j=i;j>0&&less(a[j],a[j-1]);j--)
{
exch(a,j,j-1);
}
}
}
private static boolean less(Comparable comparable, Comparable comparable2) {
// TODO 自动生成的方法存根
if(comparable.compareTo(comparable2)<0)
{
return true;
}
return false;
}
}
(2)自顶向下归并排序实现
package second_homework;
public class TDM {
private static Comparable[] aux;
private static void exch(Comparable a[],int x,int y)
{
Comparable temp = a[x];
a[x] = a[y];
a[y] = temp;
}
private static boolean less(Comparable comparable, Comparable comparable2) {
// TODO 自动生成的方法存根
if(comparable.compareTo(comparable2)<0)
{
return true;
}
return false;
}
public static void merge(Comparable a[],int lo,int mid,int hi)
{
int i=lo;
int j = mid+1;
for(int k=lo;k<=hi;k++)
aux[k] = a[k];
for(int k=lo;k<=hi;k++)
{
if(i>mid) a[k] = aux[j++];
else if(j>hi) a[k]=aux[i++];
else if(less(aux[i],aux[j]))
a[k] = aux[i++];
else
a[k] = aux[j++];
}
}
public static void sort(Comparable a[])
{
int N = a.length;
aux= new Comparable[a.length];
sort(a,0,N-1);
}
private static void sort(Comparable a[],int lo,int hi)
{
if(hi<=lo) return;
int mid = lo + (hi - lo)/2;
sort(a,lo,mid);
sort(a,mid+1,hi);
merge(a,lo,mid,hi);
}
}
(3)自底向上的归并排序实现
package second_homework;
public class BUM {
private static Comparable[] aux;
private static boolean less(Comparable comparable, Comparable comparable2) {
// TODO 自动生成的方法存根
if(comparable.compareTo(comparable2)<0)
{
return true;
}
return false;
}
public static void merge(Comparable a[],int lo,int mid,int hi)
{
int i=lo;
int j = mid+1;
for(int k=lo;k<=hi;k++)
aux[k] = a[k];
for(int k=lo;k<=hi;k++)
{
if(i>mid) a[k] = aux[j++];
else if(j>hi) a[k]=aux[i++];
else if(less(aux[j],aux[i]))
a[k] = aux[j++];
else
a[k] = aux[i++];
}
}
public static void sort(Comparable[] a)
{
int N = a.length;
aux = new Comparable[N];
for(int sz=1;sz<N;sz=sz+sz)
{
for(int lo = 0;lo<N-sz;lo+=sz+sz)
{
merge(a,lo,lo+sz-1,Math.min(N-1, lo+sz+sz-1));
}
}
}
}
(4)随机快速排序实现
package second_homework;
import edu.princeton.cs.algs4.StdRandom;
public class RQ {
private static boolean less(Comparable comparable, Comparable comparable2) {
// TODO 自动生成的方法存根
if(comparable.compareTo(comparable2)<0)
{
return true;
}
return false;
}
private static void exch(Comparable a[],int x,int y)
{
Comparable temp = a[x];
a[x] = a[y];
a[y] = temp;
}
public static void sort(Comparable[] a)
{
StdRandom.shuffle(a);
sort(a,0,a.length-1);
}
private static void sort(Comparable[] a,int lo,int hi)
{
if(hi<=lo) return;
int j = partion(a,lo,hi);
sort(a,lo,j-1);
sort(a,j+1,hi);
}
private static int partion(Comparable[] a,int lo, int hi)
{
int i=lo,j=hi+1;
Comparable v = a[lo];
while(true)
{
while(less(a[++i],v))
{
if(i == hi)
break;
}
while(less(v,a[--j]))
{
if(j==lo)
break;
}
if(i>=j)
break;
exch(a,i,j);
}
exch(a,lo,j);
return j;
}
}
(5)三向切分快速排序实现
package second_homework;
import edu.princeton.cs.algs4.StdRandom;
public class QD3P {
private static boolean less(Comparable comparable, Comparable comparable2) {
// TODO 自动生成的方法存根
if(comparable.compareTo(comparable2)<0)
{
return true;
}
return false;
}
private static void exch(Comparable a[],int x,int y)
{
Comparable temp = a[x];
a[x] = a[y];
a[y] = temp;
}
public static void sort(Comparable[] a)
{
StdRandom.shuffle(a);
sort(a,0,a.length-1);
}
private static void sort(Comparable[] a,int lo,int hi)
{
if(hi<=lo) return;
int lt=lo,i=lo+1,gt=hi;
Comparable v=a[lo];
while(i<=gt)
{
int cmp = a[i].compareTo(v);
if(cmp<0)
{
exch(a,lt++,i++);
}
else if(cmp>0)
{
exch(a,i,gt--);
}
else
i++;
}
sort(a,lo,lt-1);
sort(a,gt+1,hi);
}
}
(6)实验的主程序
package second_homework;
import edu.princeton.cs.algs4.StdRandom;
public class Sorting {
public static void show(Integer a[])
{
for(int i=0;i<a.length;i++)
{
System.out.print(a[i]);
System.out.print(" ");
if(i%10==0&&i!=0)
System.out.println();
}
System.out.println("\n-----------------------------");
}
public static void show(int a[])
{
for(int i=0;i<a.length;i++)
{
System.out.print(a[i]);
System.out.print(" ");
if(i%10==0&&i!=0)
System.out.println();
}
System.out.println("\n-----------------------------");
}
public static void main(String[] args) {
// TODO 自动生成的方法存根
System.out.println("针对100个数据进行实验");
System.out.println("原始数据如下");
int []TestData = new int[100];
Integer []TestData_1 = new Integer[100];
Integer []TestData_2 = new Integer[100];
Integer []TestData_3 = new Integer[100];
Integer []TestData_4 = new Integer[100];
Integer []TestData_5 = new Integer[100];
for(int i=0;i<100;i++)
{
TestData[i]=StdRandom.uniform(100);
TestData_1[i]=TestData_2[i]=TestData_3[i]=TestData_4[i]=TestData_5[i]=TestData[i];
}
Sorting.show(TestData);
Is.sort(TestData_1);
Sorting.show(TestData_1);
TDM.sort(TestData_2);
Sorting.show(TestData_2);
BUM.sort(TestData_3);
Sorting.show(TestData_3);
RQ.sort(TestData_4);
Sorting.show(TestData_4);
QD3P.sort(TestData_5);
Sorting.show(TestData_5);
System.out.println("这证明我的五个排序算法是正确的");
System.out.println("下面针对10000个数据进行实验,每次实验输入10次");
TestData = new int[10000];
TestData_1 = new Integer[10000];
long starttime = System.currentTimeMillis();
long endtime = System.currentTimeMillis();
long realtime = (endtime - starttime)/10;
realtime = 0;
for(int j=0;j<10;j++)
{
for(int i=0;i<10000;i++)
{
TestData[i]=StdRandom.uniform(100);
TestData_1[i] = TestData[i];
}
starttime = System.currentTimeMillis();
Is.sort(TestData_1);
endtime = System.currentTimeMillis();
realtime += (endtime - starttime);
System.out.println(endtime - starttime+"ms");
}
realtime /=10;
System.out.println("插入排序实现,排序10000个数据,重复十次,时间为"+realtime+"毫秒");
realtime = 0;
for(int j=0;j<10;j++)
{
for(int i=0;i<10000;i++)
{
TestData[i]=StdRandom.uniform(100);
TestData_1[i] = TestData[i];
}
starttime = System.currentTimeMillis();
TDM.sort(TestData_1);
endtime = System.currentTimeMillis();
realtime += (endtime - starttime);
System.out.println(endtime - starttime+"ms");
}
realtime /= 10;
System.out.println("自顶向下的归并排序实现,排序10000个数据,重复十次,时间为"+realtime+"毫秒");
realtime = 0;
for(int j=0;j<10;j++)
{
for(int i=0;i<10000;i++)
{
TestData[i]=StdRandom.uniform(100);
TestData_1[i] = TestData[i];
}
starttime = System.currentTimeMillis();
BUM.sort(TestData_1);
endtime = System.currentTimeMillis();
realtime += (endtime - starttime);
System.out.println(endtime - starttime+"ms");
}
realtime /= 10;
System.out.println("自顶向上的归并排序实现,排序10000个数据,重复十次,时间为"+realtime+"毫秒");
realtime = 0;
for(int j=0;j<10;j++)
{
for(int i=0;i<10000;i++)
{
TestData[i]=StdRandom.uniform(1000);
TestData_1[i] = TestData[i];
}
starttime = System.currentTimeMillis();
RQ.sort(TestData_1);
endtime = System.currentTimeMillis();
realtime += (endtime - starttime);
System.out.println(endtime - starttime+"ms");
}
realtime /= 10;
System.out.println("随机快速排序实现,排序10000个数据,重复十次,时间为"+realtime+"毫秒");
for(int j=0;j<10;j++)
{
for(int i=0;i<10000;i++)
{
TestData[i]=StdRandom.uniform(1000);
TestData_1[i] = TestData[i];
}
starttime = System.currentTimeMillis();
QD3P.sort(TestData_1);
endtime = System.currentTimeMillis();
realtime += (endtime - starttime);
System.out.println(endtime - starttime+"ms");
}
realtime /= 10;
System.out.println("三向切分的快排实现,排序10000个数据,重复十次,时间为"+realtime+"毫秒");
}
}
- 实验运行结果截图以及数据统计
Comparison of running time of sorting algorithms (in Micro Seconds)
|
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
Average |
IS |
181 |
188 |
97 |
106 |
118 |
99 |
109 |
99 |
99 |
97 |
129 |
TDM |
4 |
3 |
8 |
12 |
6 |
4 |
5 |
2 |
2 |
1 |
4 |
BUM |
10 |
4 |
3 |
2 |
8 |
7 |
11 |
5 |
2 |
3 |
5 |
RQ |
10 |
3 |
3 |
3 |
4 |
4 |
4 |
3 |
3 |
8 |
4 |
QD3P |
5 |
7 |
6 |
7 |
11 |
5 |
4 |
5 |
3 |
3 |
6 |
Comparison of space usage of sorting algorithms (in Kilo Bytes)
|
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
Average |
IS |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
TDM |
10 |
10 |
10 |
10 |
10 |
10 |
10 |
10 |
10 |
10 |
10 |
BUM |
10 |
10 |
10 |
10 |
10 |
10 |
10 |
10 |
10 |
10 |
10 |
RQ |
0.013 |
0.013 |
0.013 |
0.013 |
0.013 |
0.013 |
0.013 |
0.013 |
0.013 |
0.013 |
0.013 |
QD3P |
0.013 |
0.013 |
0.013 |
0.013 |
0.013 |
0.013 |
0.013 |
0.013 |
0.013 |
0.013 |
0.013 |
- 回答实验问题
1. Which sort worked best on data in constant or increasing order (i.e., already sorted data)? Why do you think this sort worked best?
回答:插入排序,因为此时,插入排序每次只要比较一次就能确定每一个元素的位置
- Did the same sort do well on the case of mostly sorted data? Why or why not?
回答:不会的,因为初始数据基本有序的情况对各种排序的影响很大,比如快排的时候,初始有序的时候就变成N2的算法
- In general, did the ordering of the incoming data affect the performance of the sorting algorithms? Please answer this question by referencing specific data from your table to support your answer.
肯定影响的,初始状况对于每一种排序的影响是巨大的,比如我使用均匀分布的十个数据,但是总数据量有10000的时候,三向切分需要6ms,而快排此时就需要33ms,原因是快排处理大量重复数据的时候是非常吃力的
- Which sort did best on the shorter (i.e., n = 1,000) data sets? Did the same one do better on the longer (i.e., n = 10,000) data sets? Why or why not? Please use specific data from your table to support your answer.
1000的时候RQ在我的算法中表现的最好,而10000的时候,数据量重复少的时候是RQ,重复多则是QD3P。比如:总数据量有10000的时候,三向切分需要6ms,而快排此时就需要33ms
- In general, which sort did better? Give a hypothesis as to why the difference in performance exists.
当然是QD3P,此时他的空间复杂度是lgN,而且也能处理大量重复数据的情况, 时间复杂度介于NlgN与N2之间,综合来看比RQ胜任更多的情况
6. Are there results in your table that seem to be inconsistent? (e.g., If I get run times for a sort that look like this {1.3, 1.5, 1.6, 7.0, 1.2, 1.6, 1.4, 1.8, 2.0, 1.5] the 7.0 entry is not consistent with the rest). Why do you think this happened?
对于数据突然出现的偶然性情况,我认为应该是初始化随机数的时候造成了一些偶然情况的发生,使得初始的排序出现了某种比较差的情况