您的位置:首页 > 其它

各种排序算法

2011-05-23 16:45 176 查看
package Exp5;
import java.util.Random;
import tools.TimeTest;
public class Sort{
/**
* variables
* */
final static  int[]  a={44,77,55,99,66,33,22,88,77};
final static String[][] SORTCOMPARE={
{"排序方法","最好时间复杂度","平均时间复杂度","最坏时间复杂度","空间复杂度","稳定性        "},
{"直接插入","O(n)      ","O(n*n)     ","O(n*n)     ","O(1)   ","	稳定       "},
{"希尔排序","```       ","O(n(1.3))  ","```        ","O(1)   ","	不稳定    "},
{"直接选择","O(n*n)    ","O(n*n)     ","O(n*n)     ","O(1)   ","	稳定       "},
{"堆排序   ","O(nlbn)   ","O(nlbn)    ","O(nlbn)    ","O(1)   ","	不稳定    "},
{"冒泡排序","O(n)      ","O(n*n)     ","O(n*n)     ","O(1)   ","	稳定       "},
{"快速排序","O(nlbn)   ","O(nlbn)    ","O(n*n)     ","O(lbn) ","	不稳定    "},
{"归并排序","O(nlbn)   ","O(nlbn)    ","O(nlbn)    ","O(n)   ","	稳定       "},
{"基数排序","O(n*m)    ","O(n*m)     ","O(n*m)     ","O(n)   ","	稳定       "}

};

/**
* main
*/
public static void main(String[] args) {

/**问题1--数组内存共享
* final static  int[]  a={44,77,55,99,66,33,22,88,77};
* int[] b=a;
* 则a与b将会共享一块内存,
* 这个时候,无论你的a是否是static final修饰的,
* 只要a改变,b就会改变,
* 只要b改变,a就会改变,
* 这样做可能是java为了提高内存的利用效率,而忽略了final关键字,
* 请查实!!
* 既然如此,只好写个copy方法来解决这个问题
* */
/**
* 问题2:mergeSort存在异常
* 解决:书上的代码是对的,附带的代码是错的...
* */
/**
* 问题三
* 改进堆排序和归并排序这两种方法,让他们更快!
* */
/**
* 各种排序方法的比较
* */
System.out.println("各种排序方法的比较");
print2(SORTCOMPARE);//输出各种排序方法的比较

/**
* 正确性验证
* */
System.out.println("正确性验证");
int[]  temp=new int[a.length];

copy(temp,a);
System.out.println("insertSort");
print(temp);
print(insertSort(temp));

copy(temp,a);//用自己写的方法,将两个数组分配到不同的内存中区,从而互不干扰
System.out.println("insertSortPro");
print(temp);
print(insertSortPro(temp));

copy(temp,a);
System.out.println("simChoseSort");
print(temp);
print(simChoseSort(temp));

copy(temp,a);
System.out.println("selectSortPro");
print(temp);
print(selectSortPro(temp));

copy(temp,a);
System.out.println("heapSort");
print(temp);
heapSort(temp );
print(temp);

copy(temp,a);
System.out.println("bubbleSort");
print(temp);
bullboSort(temp);
print(temp);

copy(temp,a);
System.out.println("bubbleSortPro");
print(temp);
print(bubbleSortPro(temp));

copy(temp,a);
System.out.println("quickSortPro");
print(temp);
quickSortPro(temp,0,temp.length-1);
print(temp);

copy(temp,a);
System.out.println("shellSort");
print(temp);
int[] b={6,3,1};
shellSort(temp,b,3);
print(temp);

copy(temp,a);
System.out.println("mergeSort");
print(temp);
try{
mergeSort(temp);
}
catch(Exception ee){
ee.printStackTrace();
}
print(temp);

copy(temp,a);
System.out.println("radixSort");
print(temp);
try {
radixSort(temp,3,10);
}
catch (Exception e) {

e.printStackTrace();
}
print(temp);

/**
* 用TimeTest类测试各种方法的运行时间
*
*/
System.out.println("用TimeTest类测试各种方法的运行时间");

int len=100000;
int[] kk=new int[len];

TimeTest timeTest=new TimeTest();
Random random=new Random();
for(int i=0;i<kk.length;i++){
kk[i]=random.nextInt(len);
}
//我讨厌这些东西......
int[] kk1=new int[len];
int[] kk2=new int[len];
int[] kk3=new int[len];
int[] kk4=new int[len];
int[] kk5=new int[len];
int[] kk6=new int[len];
int[] kk7=new int[len];
int[] kk8=new int[len];
int[] kk9=new int[len];
int[] kk0=new int[len];
int[] kka=new int[len];
int[] kkb=new int[len];
int[] kkc=new int[len];
int[] kkd=new int[len];
int[] kke=new int[len];
int[] kkf=new int[len];

copy(kk1,kk);
copy(kk2,kk);
copy(kk3,kk);
copy(kk4,kk);
copy(kk5,kk);
copy(kk6,kk);
copy(kk7,kk);
copy(kk8,kk);
copy(kk9,kk);
copy(kk0,kk);
copy(kka,kk);
copy(kkb,kk);
copy(kkc,kk);
copy(kkd,kk);
copy(kke,kk);
copy(kkf,kk);
/**
* 或许,我该写个框架来处理这些无聊而充实的重复
* */
{
print(kk1,10,10,"排序前");
timeTest.start(1, "insertSort--插入排序");
insertSort(kk1);
timeTest.stop();
print(kk1,10,10,"排序后");
}

{
print(kk2,10,10,"排序前");
timeTest.start(1, "insertSortPro--插入排序,我的版本");
insertSortPro(kk2);
timeTest.stop();
print(kk2,10,10,"排序后");
}

{
print(kk3,10,10,"排序前");
timeTest.start(1, "selectSortPro--选择排序,我的版本");
selectSortPro(kk3);
timeTest.stop();
print(kk3,10,10,"排序后");
}

{
print(kk5,10,10,"排序前");
timeTest.start(1, "quickSortPro--快速排序,我的版本");
quickSortPro(kk5,0,len-1);
timeTest.stop();
print(kk5,10,10,"排序后");
}

{
print(kk6,10,10,"排序前");
timeTest.start(1, "heapSort--堆排序");
heapSort(kk6);
timeTest.stop();
print(kk6,10,10,"排序后");
}

{
int[] d={4096,2048,1024,512,256,128,64,32,16,8,4,2,1};
print(kkc,10,10,"排序前");
timeTest.start(1, "shellSort--希尔排序");
shellSort(kkc,d,d.length);
timeTest.stop();
print(kkc,10,10,"排序后");
}

{
print(kkd,10,10,"排序前");
timeTest.start(1, "radixSort--基数排序");
try {
radixSort(kkd,5,10);
}
catch (Exception e) {
e.printStackTrace();
}
timeTest.stop();
print(kkd,10,10,"排序后");
}

{
print(kke,10,10,"排序前");
timeTest.start(1, "simChoseSort--选择排序");
simChoseSort(kke);
timeTest.stop();
print(kke,10,10,"排序后");
}

{
print(kkf,10,10,"排序前");
try{
timeTest.start(1, "mergeSort--归并排序");
mergeSort(kkf);
timeTest.stop();
}
catch(Exception e){
e.printStackTrace();
}

print(kkf,10,10,"排序后");
}

{
print(kk4,10,10,"排序前");
timeTest.start(1, "bubbleSortPro--冒泡排序,我的版本");
bubbleSortPro(kk4);
timeTest.stop();
print(kk4,10,10,"排序后");
}

{
print(kk7,10,10,"排序前");
timeTest.start(1, "bubbleSort--冒泡排序");
bullboSort(kk7);
timeTest.stop();
print(kk7,10,10,"排序后");
}
/**测试结果
* 对于int kk=new int[10000];
* `heapSort--堆排序` spends `0.047` seconds
* `mergeSort--归并排序` spends `0.047` seconds
*
* 是冒泡排序法[表现最差]107.015s的
* 2276.9148936170212765957446808511倍!
* 次优的是shellSort,0.172s完成
* `radixSort--基数排序` spends `0.813` seconds
* quickSortPro'11.563's
* insertSort`15.0` seconds
* selectSortPro`25.719` seconds
* insertSortPro`36.968` seconds//我的改进...好失败...
* simChoseSort--选择排序` spends `64.765` seconds
* bubbleSortPro`105.203` seconds//才快2s
*
* 方法越简单,速度越慢...
* 所有考试才考冒泡,
* 如果考堆和归并排序,不知道要死多少人.:)
* 下面我要改进堆排序和归并排序这两种方法,让他们更快!
* */
}
/**
* print(int[] a)
* 打印输出
* */
public static void print(int[] a){
for(int i=0;i<a.length;i++){
System.out.print(a[i]+"/t");

}
System.out.println();
}

/**
* print(int[] a,int heads,int last,String hint)
* 打印输出
* */
public static void print(int[] a,int heads,int last,String hint){
System.out.println("/t"+hint);
if(heads>=a.length||last>=a.length){
print(a);
return;
}
System.out.println("The head `"+heads+"`elements");
for(int i=0;i<heads;i++){
System.out.print(a[i]+"/t");
}
System.out.println("/t");
System.out.println("The last `"+last+"`elements");
for(int i=a.length-last;i<a.length;i++){
System.out.print(a[i]+"/t");
}
System.out.println("/t");
System.out.println("");
}
/**
* print2(String[][] aa)
* 打印输出
* */
public static void print2(String[][] aa){
for(int i=0;i<aa.length;i++){
for(int k=0;k<aa[i].length;k++){

System.out.print("/t" +aa[i][k]);

}
System.out.println();
}
}
/**
* copy(int[] a1,int[] a2)
* 把a2拷贝到a1中去
* */
public static void copy(int[] a1,int[] a2){
if(a1.length!=a2.length){
return ;
}
for(int i=0;i<a1.length;i++){
a1[i]=a2[i];
}
}

/**
* 插入排序
* insertSort(int[] a2)
* 直接插入排序
* */
public static  int[] insertSort(int[] a2){

int n=a2.length;
int i=0,j=0,temp;

for( i=0;i<n-1;i++){
temp=a2[i+1];
j=i;
while(j>-1&&temp<=a2[j]){
a2[j+1]=a2[j];
j--;
}
a2[j+1]=temp;

}
return a2;
}
/**
*  直接插入排序
*  insertSortPro(int[] a)
*  @author Allchin
* */
public static int[] insertSortPro(int[] a){
int i=1,
c=a.length,//a2.length
k=0,//
temp=0,
m=i;
for(i=1;i<c;i++){//从数组1循环到数组结束
for(k=0;k<i;k++){//循环检索已经排序的部分--就是当前元素前面的元素
if(a[k]>a[i]){//如果已排序的部分有a[k]>当前的元素
temp=a[i];//将 当前数 保存到temp

for(m=i;m>k;m--){//被插数位置后面的元素想后移动一位,到当前数位置为止
a[m]=a[m-1];
}
a[k]=temp;//被插数的位置写入当前数
}
/*
//如果已经排序的数据部分没有比当前元素大的,就什么都不干,这样就保证了数组的稳定性
//如果按照我的排序过程中的比较规则(仅当--已排序的部分有a[k]>当前的元素,才执行移动操作)
//就能够保证这个直接插入排序算法的稳定性!
*
*/
}
}
return a;
}
/**
* 插入排序
* shellSort(int[] a,int[] d,int numOfD)
* 希尔排序
* */
public static void shellSort(int[] a,int[] d,int numOfD){
int i,
j,
k,
m=0,
span,
temp,
n=a.length;

for(m=0;m<numOfD;m++){
span=d[m];
for(k=0;k<span;k++){
for(i=k;i<n-span;i=i+span){
temp=a[i+span];
j=i;
while(j>-1&&temp<=a[j]){
a[j+span]=a[j];
j=j-span;
}
a[j+span]=temp;
}
}
}

}
/**
* 交换排序
* 冒泡排序
* bullboSort(int[] a3)
* */
public static  int[] bullboSort(int[] a3){

int i=0,
j=0,
flag=1,
temp=0,
n=a3.length;

for(i=1;i<n&&flag==1;i++){
flag=0;
for(j=0;j<n-1;j++){
if(a3[j]>a3[j+1]){
flag=1;
temp=a3[j];
a3[j]=a3[j+1];
a3[j+1]=temp;
}
}
}
return a3;
}
/**
* 交换排序
* 冒泡排序
* @author Allchin
* bubbleSortPro(int[] a)
* */
public static int[] bubbleSortPro(int[] a){
int i=0,
k=0,
temp=a[0];
boolean sorted=true;
for(i=1;i<a.length;i++){
sorted=true;//初始化假设完成=true
for(k=0;k<a.length-1;k++){
if(a[k]>a[k+1]){
temp=a[k];
a[k]=a[k+1];
a[k+1]=temp;
sorted=false;//如果有排序操作,则设完成=false
}
}
if(sorted){//如果排序已经完成(上次循环没有发生交换位置操作)
return a;
}
}
return a;
}
/**
* 交换排序
* 快速排序
* quickSortPro(int[] a,int low ,int high)
* @author Allchin
* 1.从右开始扫描
* 1.1找出比目标小的数
* 1.2把比目标小的数换到目标的位置
* 2.从左扫描
* 2.1找出比目标大的数
* 2.2把比目标大的数换到目标的位置
* 3.将结束的指针位置赋予目标值
* 4.递归结束指针左边的部分
* 5.递归结束指针右边的部分
*
* */
public static int[] quickSortPro(int[] a,int low ,int high){
int j=high,
i=low,
target=a[low];
while(i<j){
for(j=high;j>low&&i<j;j--){//从右边开始扫描
if(target>a[j]){//找到比目标小的,
a[i]=a[j];//把比目标小的放到目标的位置,目标的下标成了j(暂不赋值,下面还有操作)
break;//结束从右的扫描
}
}
for(i=low;i<high&&i<j;i++){//从左开始扫描
if(target<a[i]){//找到比目标大的
a[j]=a[i];//把比目标大的,放到目标的位置,目标的下标从j变成了i(暂不赋值,下面操作)
break;//结束从左的扫描
}
}
//上面的过程不断重复;
//比target小的不断放到i的位置,就是target的左边;
//比target大的不断放到j的位置,就是target的右边;
//直到i=j;
}
a[i]=target;//此时i=j;i的位置就是target正在所在的位置
if(low<i){//用递归,把target左边的所有元素位置确定下来
quickSortPro(a,low,i-1);
}
if(i<high){//用递归,把target右边的所有元素位置确定下来
quickSortPro(a,j+1,high);//这个时候i=j,写i写j都一样
}
return a;
}
/**
* 选择排序
* simChoseSort(int[] a4)
* 直接选择排序
* */
public static  int[] simChoseSort(int[] a4){

int i=0,
j=0,

temp=0,
small=0,
n=a4.length;
for(i=0;i<n-1;i++){
small=i;
for(j=i+1;j<n;j++){
if(a4[j]<a4[small]){
small=j;
}
if(small!=i){
temp=a4[i];
a4[i]=a4[small];
a4[small]=temp;
}
}
}
return a4;
}
/**
* 选择排序
* 直接选择排序
* selectSortPro(int[] a)
* @author Allchin
* */
public static int[] selectSortPro(int[] a){
int min=a[0],//最小数的下标
i=0,
temp=0,
k=0;
for(i=0;i<a.length;i++){
min=i;
for(k=i+1;k<a.length;k++){//找出最小数的下标
min=a[k]<a[min]?k:min;
}
if(min!=i){//找到一个比a[i]小的数,就把他们两个交换位置
temp=a[i];
a[i]=a[min];
a[min]=temp;
}

}
return a;
}

/**
* 归并排序
* 二路归并排序
* mergeSort(int[] a)
* */
public static void mergeSort(int[] a){
int i;
int n=a.length;
int k=1;
int[] swap=new int
;
while(k<n){
merge(a,swap,k);
for(i=0;i<n;i++){
a[i]=swap[i];
}
k=2*k;
}

}

// 一次二路归并排序算法
// merge(int[] a,int[] swap,int k)
public static void merge(int[] a,int[] swap,int k){
int n=a.length;
int m=0,u1,l2,i,j,u2;
int l1=0;
while(l1+k<=n-1){
l2=l1+k;
u1=l2-1;
u2=(l2+k-1<=n-1)?l2+k-1:n-1;
for(i=l1,j=l2;i<=u1&&j<=u2;m++){
if(a[i]<=a[j]){
swap[m]=a[i];
i++;
}
else{
swap[m]=a[i];
j++;
}
}
while(i<=u1){
swap[m]=a[i];
m++;
i++;
}
while(j<=u2){
swap[m]=a[j];
m++;
j++;
}
l1=u2+1;

}
for(i=l1;i<n;i++,m++){
swap[m]=a[i];
}

}
/**
* 基数排序
* radixSort(int[] a, int m, int d)
* */
public static void radixSort(int[] a, int m, int d) throws Exception{
// a为要排序的数据元素,d为进制的基数,m为数据元素的最大位数
int n = a.length;
int i, j, k, l, power = 1;
LinQueue[] myQueue = new LinQueue[d];

//创建链式队列数组对象
for(i = 0; i < d; i++){
LinQueue temp = new LinQueue();
myQueue[i] = temp;
}

//进行m次排序
for(i = 0; i < m; i++){
if(i == 0) power = 1;
else power = power * d;

//依次将n个数据元素按第k位的大小放到相应的队列中
for(j = 0; j < n; j++){
k = a[j] / power - (a[j] / (power * d)) * d;	//计算k值
myQueue[k].append(new Integer(a[j]));			// a[j]入队列k
}
//顺序回收各队列中的数据元素到数组a中
l = 0;
for(j = 0; j < d; j++){
while(myQueue[j].notEmpty()){
a[l] = ((Integer)myQueue[j].delete()).intValue();
l++;
}
}
}
}
/**
* 选择排序
* 堆排序
* heapSort(int[] a)
* */
public static void heapSort(int[] a){
int temp;
int n = a.length;

initCreateHeap(a); 				//初始化创建最大堆

for(int i = n - 1; i > 0; i --){	//当前最大堆个数每次递减1
//把堆顶a[0]元素和当前最大堆的最后一个元素交换
temp = a[0];
a[0] = a[i];
a[i] = temp;
createHeap(a,i, 0); 			//调整根结点满足最大堆
}
}
public static void createHeap(int[] a, int n, int h){
int i, j, flag;
int temp;

i = h; 		        					// i为要建堆的二叉树根结点下标
j = 2 * i + 1; 						// j为i结点的左孩子结点的下标
temp = a[i];
flag = 0;
//沿左右孩子中值较大者重复向下筛选
while(j < n && flag != 1){
//寻找左右孩子结点中的较大者,j为其下标
if(j < n - 1 && a[j] < a[j + 1]) j++;
if (temp > a[j]) 					//a[i]>a[j]
flag = 1; 					//标记结束筛选条件
else{							//否则把a[j]上移
a[i] = a[j];
i = j;
j = 2 * i + 1;
}
}
a[i] = temp; 							//把最初的a[i]赋予最后的a[j]
}

public static void initCreateHeap(int[] a){
int n = a.length;
for(int i = (n - 1) / 2; i >= 0; i --)
createHeap(a, n, i);
}

}


package tools;
import java.io.*;
import java.util.*;
public class TimeTest {
/**
* valiables
* */
public static PrintStream out=System.out;

private double startTime=0,
endTime=0,
times=0;
private String title="";
/**
* Methods
* */
public void runWhat() {
}
/**
* doItForTimes(int times,String title)
* 流程控制
* 适用于整个类测试,这个类是本类的子类,并重写runWhat方法
* */
public void doItForTimes(int times,String title) {
start(times,title);
for(int i=0;i<times;i++){//执行run方法
runWhat();
}
stop();

}
/**
* start(int times,String title)
* */
public void start(int times,String title){
this.times=times;
this.title=title;
out.println("Methods`"+title+"` will run for `"+times+"`times");
startTime=new Date().getTime();//开始计时
}
/**
* stop()
* */
public void stop(){
endTime=new Date().getTime();//结束计时
out.println("Methods`"+title+"` had run for `"+times+"`times in`"+((endTime-startTime)/1000)+"`seconds");
out.println("Each of the Methods`"+title+"` spends `"+(((endTime-startTime)/times)/1000)+"` seconds");
out.println();
}
}

package Exp5;
public interface Queue{
public void append(Object obj) throws Exception;
public Object delete() throws Exception;
public Object getFront() throws Exception;
public boolean notEmpty();
}

package Exp5;
public class Node{

Object element;
Node next;

Node(Object obj,Node nextval){
element = obj;
next = nextval;
}

Node(Node nextval){
next = nextval;
}

public Node getNext(){
return next;
}

public void setNext(Node nextval){
next = nextval;
}

public Object getElement(){
return element;
}

public void setElement(Object obj){
element = obj;
}
public String toString(){
return element.toString();
}
}

package Exp5;
public class LinQueue implements Queue{
Node front;
Node rear;
int count;

public LinQueue(){
initiate();
}

public LinQueue(int sz){
initiate();
}

private void initiate(){
front = rear = null;
count = 0;
}

public void append(Object obj){
Node newNode = new Node(obj,null);

if(rear != null)
rear.next = newNode;
rear = newNode;
if(front == null)
front = newNode;
count ++;
}

public Object delete() throws Exception{
if(count == 0)
throw new Exception("队列已空!");

Node temp = front;
front = front.next;
count --;
return temp.getElement();
}

public Object getFront() throws Exception{
if(count == 0)
throw new Exception("队列已空!");
return front.getElement();
}

public boolean notEmpty(){
return count != 0;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: