1. 冒泡排序
基本思想:在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对
相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的
数比较后发现它们的排序与排序要求相反时,就将它们互换。
2. 选择排序
选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法(比如序列[5, 5, 3]第一次就将第一个[5]与[3]交换,导致第一个5挪动到第二个5后面)。
3. 插入排序
所谓插入排序法,就是检查第i个数字,如果在它的左边的数字比它大,进行交换,这个动作一直继续下去,直到这个数字的左边数字比它还要小,就可以停止了。插入排序法主要的回圈有两个变数:i和j,每一次执行这个回圈,就会将第i个数字放到左边恰当的位置去。
4. 堆排序
堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]] >= A[i]。在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。
5. 快速排序
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
6. 基数排序
基数排序(radix sort)属于“分配式排序”(distributionsort),又称“桶子法”(bucket sort)或bin sort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序,其时间复杂度为O (nlog(r)m),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的稳定性排序法。
java 代码实例:
package com.gnet.module.talk;
public class RainTest extends Thread {
static int[] num={9,10,4,5,2,1,6,3,7,8};
static int MAX=num.length;
/*-------------------------插入排序法--------------------------------
像是玩朴克一样,我们将牌分作两堆,每次从后面一堆的牌抽出最前端的牌,然后插入前面一堆牌的适当位置
-----------------------------------------------------------------*/
public void insort(int number[]){
int i, j, k, temp;
long start,end;
start=System.nanoTime();
for(j = 1; j < MAX; j++) {
temp = number[j];
i = j - 1;
while(temp < number[i]) {
number[i+1] = number[i];
i--;
if(i == -1){
break;
}
}
number[i+1] = temp;
}
end=System.nanoTime();
System.out.println("-----------------插入排序法------------------");
System.out.print("排序后是:");
for(i=0;i<MAX;i++){
System.out.print(number[i]+" ");
}
System.out.println();
System.out.println("排序使用时间:"+(end-start)+" ns");
}
/*----------------------------选择排序法-------------------------------------------
将要排序的对象分作两部份,一个是已排序的,一个是未排序的,从后端未排序部份选择一个最小值,并放入前端已排序部份的最后一个。
-------------------------------------------------------------------------------*/
public void selsort(int number[]) {
int i, j, k, m, temp;
long start,end;
start=System.nanoTime();
for(i = 0; i < num.length; i++) {
m = i;
for(j = i; j < num.length; j++){
if(number[j] < number[m]){
m = j;
}
}
if( i != m){
temp=number[i];
number[i]=number[m];
number[m]=temp;
}
}
end=System.nanoTime();
System.out.println("-----------------选择排序法------------------");
System.out.print("排序后是:");
for(i=0;i<num.length;i++){
System.out.print(number[i]+" ");
}
System.out.println();
System.out.println("排序使用时间:"+(end-start)+" ns");
}
//-----------------冒泡排序法------------------
public void bubsort(int number[]){
int i, j, k, temp, flag = 1;
long start,end;
int MAX=num.length;
start=System.nanoTime();
for(i = 0; i <MAX ; i++) {
for(j = i; j < MAX; j++) {
if(number[j] < number[i]) {
temp=number[j];
number[j]=number[i];
number[i]=temp;
}
}
}
end=System.nanoTime(); //返回的是纳秒
System.out.println("-----------------冒泡排序法------------------");
System.out.print("排序后是:");
for(i=0;i<num.length;i++){
System.out.print(number[i]+" ");
}
System.out.println();
System.out.println("排序使用时间:"+(end-start)+" ns");
}
/*-----------------------heap排序(堆排序法--改进的选择排序)----------------------------
利用堆积树的原理,先构造一个堆积树(看堆积树的定义,笔记本上有),然后将根节点与最后的叶子节点交换,并屏蔽掉最后一个叶子节点,
然后再将未被屏蔽的部分重新构造堆积树,然后再重复上面的步骤,直到所有的数被按顺序排好。
--------------------------------------------------------------------------------*/
public void heapsort(int number[]) {
int i, m, p, s, temp;
long start,end;
start=System.nanoTime();
int number_temp[]=new int[MAX+1];
for(int temp_i=1;temp_i<MAX+1;temp_i++){
number_temp[temp_i]=number[temp_i-1];
}
createheap(number_temp);
m = MAX;
while(m > 1) {
temp=number_temp[1];
number_temp[1]=number_temp[m];
number_temp[m]=temp;
m--;
p = 1;
s = 2 * p;
while(s <= m) {
if(s < m && number_temp[s+1] > number_temp[s])
s++;
if(number_temp[p] >= number_temp[s])
break;
temp=number_temp[p];
number_temp[p]=number_temp[s];
number_temp[s]=temp;
p = s;
s = 2 * p;
}
}
for(int temp_j=1;temp_j<MAX+1;temp_j++){
number[temp_j-1]=number_temp[temp_j];
}
end=System.nanoTime();
System.out.println("-----------------heap排序(堆排序法--改进的选择排序)------------------");
System.out.print("排序后是:");
for(i=0;i<=MAX-1;i++){
System.out.print(number[i]+" ");
}
System.out.println();
System.out.println("排序使用时间:"+(end-start)+" ns");
}
//将原数组构造为从下标1开始的一个新数组,便于处理,同时将这个新数组构造为最初始的堆积树结构
public void createheap(int number[]) {
int i, s, p, temp;
int heap[] = new int[MAX+1];
for(i = 1; i <= MAX; i++) {
heap[i] = number[i];
s = i;
p = i / 2;
while(s >= 2 && heap[p] < heap[s]) {
temp=heap[p];
heap[p]=heap[s];
heap[s]=temp;
s = p;
p = s / 2;
}
}
for(i = 1; i <= MAX; i++){
number[i] = heap[i];
}
}
/*-----------------------快速排序法(一)---------------------------------------------
这边所介绍的快速演算如下:将最左边的数设定为轴,并记录其值为s
廻圈处理:
令索引i 从数列左方往右方找,直到找到大于s 的数
令索引j 从数列左右方往左方找,直到找到小于s 的数
如果i >= j,则离开回圈
如果i < j,则交换索引i与j两处的值
将左侧的轴与j 进行交换
对轴左边进行递回
对轴右边进行递回
--------------------------------------------------------------------------------*/
public void quicksort_one(int number[]){
long start,end;
start=System.nanoTime();
quicksort_1(number,0,MAX-1);
end=System.nanoTime();
System.out.println("-----------------快速排序法( 一 )------------------");
System.out.print("排序后是:");
for(int i=0;i<=MAX-1;i++){
System.out.print(number[i]+" ");
}
System.out.println();
System.out.println("排序使用时间:"+(end-start)+" ns");
}
//数组,第一个索引,最后一个索引
public void quicksort_1(int number[],int left,int right) {
int i, j, s, temp;
if(left < right) {
s = number[left];
i = left;
j = right + 1;
while(true) {
// 向右找 1<10&&num[1]<num[0]
while(i + 1 < number.length && number[++i] < s) ;
// 向左找 9>-1&&num[9]>num[1]
while(j -1 > -1 && number[--j] > s) ;
if(i >= j)
break;
temp=number[i];
number[i]=number[j];
number[j]=temp;
}
number[left] = number[j];
number[j] = s;
quicksort_1(number, left, j-1); // 对左边进行递回
quicksort_1(number, j+1, right); // 对右边进行递回
}
}
/*-----------------------快速排序法(二)---------------------------------------------
在这个例子中,取中间的元素s作比较,同样的先得右找比s大的索引i,然后找比s小的
索引j,只要两边的索引还没有交会,就交换i 与j 的元素值,这次不用再进行轴的交换了,
因为在寻找交换的过程中,轴位置的元素也会参与交换的动作,例如:
41 24 76 11 45 64 21 69 19 36
首先left为0,right为9,(left+right)/2 = 4(取整数的商),所以轴为索引4的位置,比较的元素是
45,您往右找比45大的,往左找比45小的进行交换:
41 24 76* 11 [45] 64 21 69 19 *36
41 24 36 11 45* 64 21 69 19* 76
41 24 36 11 19 64* 21* 69 45 76
[41 24 36 11 19 21] [64 69 45 76]
完成以上之后,再初别对左边括号与右边括号的部份进行递回,如此就可以完成排序的目的。
--------------------------------------------------------------------------------*/
public void quicksort_two(int number[]){
long start,end;
start=System.nanoTime();
quicksort_2(number,0,MAX-1);
end=System.nanoTime();
System.out.println("-----------------快速排序法( 二 )------------------");
System.out.print("排序后是:");
for(int i=0;i<=MAX-1;i++){
System.out.print(number[i]+" ");
}
System.out.println();
System.out.println("排序使用时间:"+(end-start)+" ns");
}
public void quicksort_2(int number[], int left, int right) {
int i, j, s, temp;
if(left < right) {
s = number[(left+right)/2];
i = left - 1;
j = right + 1;
while(true) {
while(number[++i] < s) ; // 向右找
while(number[--j] > s) ; // 向左找
if(i >= j)
break;
temp=number[i];
number[i]=number[j];
number[j]=temp;
}
quicksort_2(number, left, i-1); // 对左边进行递回
quicksort_2(number, j+1, right); // 对右边进行递回
}
}
/*-----------------------快速排序法(三)---------------------------------------------
先说明这个快速排序法的概念,它以最右边的值s作比较的标准,将整个数列分为三个部份,
一个是小于s的部份,一个是大于s的部份,一个是未处理的部份,如下所示:
i j
--------|-----------|----------|s
小于s 大于s 未处理
在排序的过程中,i 与j 都会不断的往右进行比较与交换,最后数列会变为以下的状态:
-------------|-----------------|s
小于s 大于s
然后将s的值置于中间,接下来就以相同的步骤会左右两边的数列进行排序的动作,如下所示:
-------------|s|---------------
小于s 大于s
然后采用递归的方法重复上面的步骤,就可以实现排序了。
--------------------------------------------------------------------------------*/
public void quicksort_three(int number[]){
long start,end;
start=System.nanoTime();
quicksort_3(number,0,MAX-1);
end=System.nanoTime();
System.out.println("-----------------快速排序法( 三 )------------------");
System.out.print("排序后是:");
for(int i=0;i<=MAX-1;i++){
System.out.print(number[i]+" ");
}
System.out.println();
System.out.println("排序使用时间:"+(end-start)+" ns");
}
public int partition(int number[], int left, int right) {
int i, j, s, temp;
s = number[right];
i = left - 1;
for(j = left; j < right; j++) {
if(number[j] <= s) {
i++;
temp=number[i];
number[i]=number[j];
number[j]=temp;
}
}
temp=number[i+1];
number[i+1]=number[right];
number[right]=temp;
return i+1;
}
public void quicksort_3(int number[], int left, int right) {
int q;
if(left < right) {
q = partition(number, left, right);
quicksort_3(number, left, q-1);
quicksort_3(number, q+1, right);
}
}
//基数
/*-----------------------基数排序法---------------------------------------------
基数排序的方式可以采用LSD(Least sgnificant digital)或MSD(Most sgnificant digital),
LSD的排序方式由键值的最右边开始,而MSD则相反,由键值的最左边开始。
以LSD为例,假设原来有一串数值如下所示:
73, 22, 93, 43, 55, 14, 28, 65, 39, 81
首先根据个位数的数值,在走访数值时将它们分配至编号0到9的桶子中:
0 1 2 3 4 5 6 7 8 9
81 65 39
43 14 55 28
93
22 73
接下来将这些桶子中的数值重新串接起来,成为以下的数列:
81, 22, 73, 93, 43, 14, 55, 65, 28, 39
接着再进行一次分配,这次是根据十位数来分配:
接下来将这些桶子中的数值重新串接起来,成为以下的数列:
0 1 2 3 4 5 6 7 8 9
28 39
14 22 43 55 65 73 81 93
14, 22, 28, 39, 43, 55, 65, 73, 81, 93
这时候整个数列已经排序完毕;如果排序的对象有三位数以上,则持续进行以上的动作直至最
高位数为止。
LSD的基数排序适用于位数小的数列,如果位数多的话,使用MSD的效率会比较好,MSD的方
式恰与LSD相反,是由高位数为基底开始进行分配,其他的演算方式则都相同。
--------------------------------------------------------------------------------*/
public void basesort(int number[]){
int temp[][] = new int[MAX][MAX];
int order[] = new int[MAX];
int i, j, k, n, lsd;
long start,end;
k = 0;
n = 1;
start=System.nanoTime();
while(n <= 10) {
for(i = 0; i < MAX; i++) {
lsd = ((number[i] / n) % 10);
temp[lsd][order[lsd]] = number[i];
order[lsd]++;
}
//重新排列
for(i = 0; i < MAX; i++) {
if(order[i] != 0)
for(j = 0; j < order[i]; j++) {
number[k] = temp[i][j];
k++;
}
order[i] = 0;
}
n *= 10;
k = 0;
}
end=System.nanoTime();
System.out.println("-----------------基数排序法------------------");
System.out.print("排序后是:");
for(int ii=0;ii<=MAX-1;ii++){
System.out.print(number[ii]+" ");
}
System.out.println();
System.out.println("排序使用时间:"+(end-start)+" ns");
}
public static void main(String[] args) throws Exception {
RainTest t=new RainTest();
t.bubsort(num);
t.selsort(num);
t.insort(num);
t.heapsort(num);
t.quicksort_one(num);
t.quicksort_two(num);
t.quicksort_three(num);
t.basesort(num);
}
}