算法上机报告2 ——几种排序算法的实验性能比较(插入排序,归并排序,随机快排,三路随机快排)
算法上机报告2
——几种排序算法的实验性能比较
目录
四、实验内容(含源码)
一、实验简介
本实验要求学生能够综合运用排序、搜索、图处理和字符串处理的基础算法和数据结构,
将算法理论、算法工程和编程实践相结合开发相应的软件,解决科学、工程和应用环境下的
实际问题。使学生能充分运用并掌握算法设计与分析的方法以及算法工程技术,为从事计算
机工程和软件开发等相关工作打下坚实的基础。
二、实验目的
通过本课程的学习使学生系统掌握算法设计与分析的基本概念和基本原理,理解排序、
搜索、图处理和字符串处理的算法设计理论及性能分析方法,掌握排序、搜索、图处理和字符串处理的数据结构与算法实现技术。课程强调算法的开发及 Java 实现,理解相应算法的性能特征,评估算法在应用程序中的潜在性能。
三、实验环境
1.安装Windows操作系统的计算机
2.Java的IDE——eclipse
3.安装 Java 编程环境。 引入stdlib.jar and algs4.jar。
四、实验内容
1.问题重述
实现插入排序(Insertion Sort,IS),自顶向下归并排序(Top-down Mergesort,TDM),
自底向上归并排序(Bottom-up Mergesort,BUM),随机快速排序(Random Quicksort,
RQ),Dijkstra 3-路划分快速排序(Quicksort with Dijkstra 3-way Partition,QD3P)。在你的
计算机上针对不同输入规模数据进行实验,对比上述排序算法的时间及空间占用性能。要
求对于每次输入运行 10 次,记录每次时间/空间占用,取平均值。
2.问题求解
插入排序,也即冒泡排序,其时间复杂度为平方级别,图示如下
自顶向下的归并排序,由于单个的元素必然有序,基于此,可以将原数组不断的分治,直到一个元素的时候递归返回,图示如下
自底向上的归并排序,仍然基于单个元素有序,我们可以将元素两两归并,然后四四归并,直至对整个数组排好序,图示如下
随机快排,该算法基于切分和分治,每一次切分都会排定一个元素,直到正确的将整个数组排好序,图示如下
三路随机快排,是随机快排的一种改进算法,可以更高效的处理切分元素值有重复的情况,即将数组切分为三部分——大于、小于、等于切分元素,图示如下
3.实验结果
由此知,对于100000个随机数,各算法用时比较如下
插入排序>>随机快速排序≈Dijkstra 3-路划分快速排序>自顶向下归并排序≈自底向上归并排序
4.源代码
1插入排序
package InsertionSort;
import java.util.Random;
import QuicksortwithDijkstra_3wayPartition.QD3P;
public class InsertSort {
private static void exchange(int[] a,int i,int j){
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
public static void sort(int[] a){
for(int i=1;i<a.length;++i){
for(int j=i;j>0&&less(a[j],a[j-1]);--j){
exchange(a, j, j-1);
}
}
}
private static boolean less(int x, int y) {
return x<y;
}
public static void display(int[] a){
for(int i=0;i<a.length;++i)
System.out.print(a[i] + " ");
System.out.println();
}
public static void main(String[] args) {
int[] a = new int[100000];
Random r = new Random();
for(int i=0;i<100000;++i){
a[i]=r.nextInt()%40000;
}
System.out.println("处理数据数量:100000");
//display(a);
long startTime3 = System.currentTimeMillis();//获取当前时间
InsertSort.sort(a);
long endTime3 = System.currentTimeMillis();
System.out.println("程序运行时间:"+(endTime3-startTime3)+"ms");
}
}
2自顶向下归并排序
package TopDownMergesort;
import java.util.Random;
import QuicksortwithDijkstra_3wayPartition.QD3P;
public class TPMergeSort {
private static int[] aux;
public static void sort(int[] a) {
aux = new int[a.length];
sort(a,0,a.length-1);
}
private static void sort(int[] 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);
}
private static void merge(int[] 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++];
}
}
private static boolean less(int a, int b) {
if(a < b)
return true;
else
return false;
}
public static void display(int[] a){
for(int i=0;i<a.length;++i)
System.out.print(a[i] + " ");
}
public static void main(String[] args) {
int[] a = new int[100000];
Random r = new Random();
for(int i=0;i<100000;++i){
a[i]=r.nextInt()%40000;
}
System.out.println("处理数据数量:100000");
//display(a);
long start_time=System.nanoTime();//获取当前时间
sort(a);
long consumingtime=System.nanoTime()-start_time;
System.out.println("程序运行时间:"+(consumingtime/1000)/1000.0+"ms");
}
}
3自底向上归并排序
package BottomUpMergesort;
import java.util.Random;
public class BUMergesort {
private static int[] aux;
public static void sort(int[] a) {
int N = a.length;
aux = new int[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(lo+sz+sz-1, N-1));
}
}
}
private static void merge(int[] 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 boolean less(int a, int b) {
if(a < b)
return true;
else
return false;
}
public static void display(int[] a){
for(int i=0;i<a.length;++i)
System.out.print(a[i] + " ");
}
public static void main(String[] args) {
int[] a = new int[100000];
Random r = new Random();
for(int i=0;i<100000;++i){
a[i]=r.nextInt()%40000;
}
System.out.println("处理数据数量:100000");
//display(a);
long start_time=System.nanoTime();//获取当前时间
sort(a);
long consumingtime=System.nanoTime()-start_time;
System.out.println("程序运行时间:"+(consumingtime/1000)/1000.0+"us");
}
}
4随机快速排序
package Quicksort;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import InsertionSort.InsertSort;
public class QuictSort {
private static boolean less(int x,int y){
return x<y;
}
private static void exchange(int[] a,int i,int j){
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
private static void sort(int[] a){
List<Integer> list_a = new ArrayList<Integer>();
for(int i=0;i<a.length;++i){
list_a.add(a[i]);
}
Collections.shuffle(list_a);
sort(a,0,a.length-1);
}
public static void sort(int[] a,int lo,int hi ){
if(hi<=lo)
return ;
int j = partition(a, lo, hi);
sort(a,lo,j-1);
sort(a,j+1,hi);
}
private static int partition(int[] a,int lo,int hi){
int i=lo;
int j=hi+1;
while(true){
while(less(a[++i],a[lo])){
if(i==hi){
break;
}
}
while(less(a[lo],a[--j])){
if(j==lo){
break;
}
}
if(i>=j)
break;
exchange(a,i,j);
}
exchange(a,lo,j);
return j;
}
public static void display(int[] a){
for(int i=0;i<a.length;++i)
System.out.print(a[i] + " ");
System.out.println();
}
public static void main(String[] args) {
int[] a = new int[100000];
Random r = new Random();
for(int i=0;i<100000;++i){
a[i]=r.nextInt()%40000;
}
System.out.println("处理数据数量:100000");
//display(a);
long start_time=System.nanoTime();//获取当前时间
QuictSort.sort(a);
long consumingtime=System.nanoTime()-start_time;
System.out.println("程序运行时间:"+(consumingtime/1000)/1000.0+"us");
}
}
5Dijkstra 3-路划分快速排序
package QuicksortwithDijkstra_3wayPartition;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import Quicksort.QuictSort;
public class QD3P {
private static int compare(int x,int y){
if(x<y)
return -1;
else if(x>y)
return 1;
else
return 0;
}
private static void exchange(int[] a,int i,int j){
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
private static void sort(int[] a){
List<Integer> list_a = new ArrayList<Integer>();
for(int i=0;i<a.length;++i){
list_a.add(a[i]);
}
Collections.shuffle(list_a);
sort(a,0,a.length-1);
}
private static void sort(int[] a,int lo,int hi){
if(hi<=lo)
return;
int lt=lo;
int gt=hi;
int i=lo;
int v = a[lo];
while(i <= gt){
int cmp = compare(a[i],v);
if(cmp<0)
exchange(a, lt++, i++);
else if(cmp>0)
exchange(a, i, gt--);
else
i++;
}
sort(a,lo,lt-1);
sort(a,gt+1,hi);
}
public static void display(int[] a){
for(int i=0;i<a.length;++i)
System.out.print(a[i] + " ");
System.out.println();
}
public static void main(String[] args) {
int[] a = new int[100000];
Random r = new Random();
for(int i=0;i<100000;++i){
a[i]=r.nextInt()%40000;
}
System.out.println("处理数据数量:100000");
//display(a);
long start_time=System.nanoTime();//获取当前时间
QD3P.sort(a);
long consumingtime=System.nanoTime()-start_time;
System.out.println("程序运行时间:"+(consumingtime/1000)/1000.0+"us");
}
}
五、实验感想
几种排序算法虽然基本,但是其中的思想非常值得我好好学习,归并排序和快速排序采用了分治法,经典而有效地将低级排序算法如插入排序将时间复杂度从n^2降为nlogn。书中给的代码非常简洁,在实际编写程序的过程中我采用了书中的框架,感受到了算法的魅力。