排序算法根据不同的算法思想往往有很多不同的实现。近期,个人整理了常见的七种算法,并用java对各个算法进行了具体实现,包括:插入排序、冒泡排序、选择排序、shell排序、归并排序、快速排序以及堆排序。
一、插入排序
算法步骤:
从第二个数值开始依次往后遍历。将第k个数值放到前面已经排好序的k-1个数值的合适位置。所谓的合适位置(以从小到大排序为例)就是该位置的前一个数值小于number[k],而后一个位置的数值大于number[k]。
移动方法,依次比较k-1到0的所有数值,如果number[k]小于它前一个位置的数,就交换两个数的位置。
过程示例:
核心代码:
//插入排序
public static int[] insertSort(int[] number){
for(int i=1;i<number.length;i++){
int processPosition=i;
for(int j=i-1;j>=0;j--){
if(number[processPosition]<number[j]){
int temp=number[processPosition];
number[processPosition]=number[j];
number[j]=temp;
processPosition=j;
}
else break;
}
}
return number;
}
二、冒泡排序
算法步骤:
总共进行n-1趟(n为数组长度)。每一趟都能取出未排序序列中的最小值,然后放到未排序序列的最前面,也就是第k趟取出的是整个序列中第k小的值。
移动方法,从最后一个数往前移动,比较相邻两个位置上数的大小,如果number[k]小于number[k-1],就交换两个数值的位置。
过程示例:
核心代码:
//冒泡排序
public static int[] bubblingSort(int[] number){
for(int i=0;i<number.length;i++){
for(int j=number.length-1;j>i;j--){
if(number[j]<number[j-1]){
int temp=number[j];
number[j]=number[j-1];
number[j-1]=temp;
}
}
}
return number;
}
三、选择排序
算法过程:
过程和冒泡排序差不多,只不过它只做最后的那次交换。
过程示例:
核心代码:
//选择排序
public static int[] chooseSort(int[] number){
for(int i=0;i<number.length;i++){
int minValuePosition=number.length-1;
for(int j=number.length-2;j>=i;j--){
if(number[minValuePosition]>number[j]){
minValuePosition=j;
}
}
int temp=number[i];
number[i]=number[minValuePosition];
number[minValuePosition]=temp;
}
return number;
}
四、shell排序
算法步骤:
选择一个初始增量,对距离为该增量的数值序列进行插入排序。不断缩小增量,不断进行插入排序。直到增量为1,最后进行一次排序后终止,即可得到结果。
过程示例:
核心代码:
//shell排序
public static int[] shellSort(int[] number){
//选择增量
for(int i=number.length/2;i>=1;i=i/2){
for(int j=0;j<i;j++){
insSort(number,j,i);
}
}
return number;
}
//shell排序中的插入排序
private static int[] insSort(int[] number,int start, int inc) {
for(int i=start;i<number.length;i+=inc){
int processPosition=i;
for(int j=i-1;j>=start;j-=inc){
if(number[processPosition]<number[j]){
int temp=number[j];
number[j]=number[processPosition];
number[processPosition]=temp;
processPosition=j;
}
else break;
}
}
return number;
}
五、归并排序
算法步骤:
基于二分法的思想,每次都把待排序列划分为两个部分,对两个部分进行排序。运行递归不断缩小待排序列的规模,终止条件为待排序列大小为1时。当两个部分已排好序时,对其进行合并,依次比较两个部分的最小值,取出更小的数值存入临时数组中。
过程示例:
核心代码:
//归并排序
public static void mergeSort(int[] number,int start,int len){
if(len==1) return;
int half=start+len/2-1;
mergeSort(number,start,len/2);
mergeSort(number,half+1,len/2);
merge(number,start,len);
}
//归并排序的数组合并函数
private static void merge(int[] number, int start, int len) {
System.out.println("合并后的数组:"+start+" "+len);
int leftstart=start;
int leftend=start+len/2-1;
int rightstart=start+len/2;
int rightend=start+len-1;
int[] temp=new int[len];
int position=0;
while(position<temp.length){
if((leftstart<=leftend)&&(rightstart<=rightend)){
if(number[leftstart]<number[rightstart]){
temp[position]=number[leftstart];
position++;
leftstart++;
}
else{
temp[position]=number[rightstart];
position++;
rightstart++;
}
}
else if(leftstart>leftend){
for(int i=rightstart;i<=rightend;i++){
temp[position]=number[i];
position++;
}
break;
}
else if(rightstart>rightend){
for(int i=leftstart;i<=leftend;i++){
temp[position]=number[i];
position++;
}
break;
}
}
for(int i=0;i<len;i++){
number[start+i]=temp[i];
}
}
六、快速排序
算法思想:
确定一个轴值。把在轴值左边并且比它大的数据放到它的右边,把在轴值右边并且比它小的数据放到左边。
过程示例:
核心代码:
//快速排序
public static void qSort(int[] number,int start,int end){
if(end<=start) return;
int devided=partition(number,start,end);
qSort(number,start,devided-1);
qSort(number,devided+1,end);
}
//排序的核心代码
private static int partition(int[] number, int start, int end) {
int half=(end-start)/2+start;
int l=start,r=end;
while(l<r){
while((number[l]<=number[half])&&(l<end)){
l++;
}
while((r>l)&&(number[r]>=number[half])) r--;
swap(number,l,r);
}
if(((l<half)&&(number[l]>number[half]))||((l>half)&&(number[l]<number[half]))){
//改变轴值的位置
swap(number,l,half);
}
return l;
}
//交换函数
private static void swap(int[] number, int i, int j) {
int temp=number[i];
number[i]=number[j];
number[j]=temp;
}
七、堆排序
堆排序由于需要建树,比较复杂。这里只给我的测试代码,堆的构建和具体的算法思想可以看我的另一篇博客:《堆的实现(数据结构)》
测试代码:
//测试代码
ArrayList<Node>nodeList=new ArrayList();
nodeList.add(new Node(1,"A"));
nodeList.add(new Node(9,"B"));
nodeList.add(new Node(3,"C"));
nodeList.add(new Node(6,"D"));
nodeList.add(new Node(7,"E"));
Heap heap=new Heap(nodeList);
heap.buildHeap();
System.out.println("当前的堆结构");
for(int i=0;i<heap.length();i++){
System.out.println(heap.nodeList.get(i).key+"-"+heap.nodeList.get(i).value);
}
System.out.println("堆排序后的结果");
int max=heap.length();
for(int j=0;j<max;j++){
Node result=heap.removeFirst();
System.out.println(result.key+result.value);
}
整个程序完整的代码较长,这里就不放上来了,有需要的可以留言。