看来网上的一些快速排序的例子,发现好多都是代码比较多且不好理解,所以想自己总结一遍这样的博文
来分析快速排序,贴出了java实现的代码,用其他语言实现只要稍作修改就行。
s[]={48,89,34,55,11,56,89,96,10};
以数组s[]为实例来剖析快速排序代码的原理:数组的初始太:选48做基准数,对数组进行填坑挖数操作
X=s[0],i=0,j=8
48 | 89 | 34 | 55 | 11 | 56 | 89 | 96 | 10 |
2.从最右边开始向左找一个小于48的数,并在此处挖一个坑(挖坑处用红色的00表示)
X=48,i=0, j=8
将a[j]的值填到a[i]处(a[i]=a[j]),并在i处挖一个坑(挖坑处用红色00表示)
10 | 89 | 34 | 55 | 11 | 56 | 89 | 96 | 00 |
3.从最左边开始向右找一个大于48的数
X=48,i=1, j=8
将a[i]的值填到a[j]处(a[j]=a[i]),并在i处挖一个坑(挖坑处用红色00表示)
10 | 00 | 34 | 55 | 11 | 56 | 89 | 96 | 89 |
类似的进行步骤2,后得
X=48,i=1, j=4
10 | 11 | 34 | 55 | 00 | 56 | 89 | 96 | 89 |
类似的进行步骤3,后得
X=48,i=3, j=4
10 | 11 | 34 | 00 | 55 | 56 | 89 | 96 | 89 |
再进行2步骤发现i=j=3,令a[3]=48;得数组
10 | 11 | 34 | 48 | 55 | 56 | 89 | 96 | 89 |
此时对数组:使用分治法思想(观察数组知道,经过填坑挖数操作后的数组有以下特征:
以48为分界线,48左边的数都小于48,48右边的数都大于48)
将数组分为
10 | 11 | 34 |
和
55 | 56 | 89 | 96 | 89 |
,然后对两个子数组分而治之:就是对子数组分别做填坑挖数的操作,之后又会产生4个子数组,
直到子数组子只含有一个元素,停止划分。(很容易看出子数组和原数组都在调用填坑挖数的
操作,从而看出这里有一个递归的思想,所以想到递归的办法)
/**
* @author 源泉之志
* 快速排序:填坑挖数+分治法
* 快速排序一种易于理解的方式实现
* Divide-and-ConquerMethod
*
*/
public class QuickSort {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int s[]={48,89,34,55,11,56,89,96,2};
QuickSort qs = new QuickSort();
qs.quick_sort(s, 0, s.length-1);
System.out.println("输出数组");
for(int i=0;i<s.length;i++){
System.out.print(s[i]+" ");
}
}
/**
* 填坑挖数的代码
* @param s
* @param l
* @param r
* int i=l, j=r;
* 1.选一个基准量,X=s[i]
* 2.从s[j]处开始从右往左找,找到第一个小于X的值,找到后把s[j]的值赋给s[i]
* 3.从s[i]处开始从左往右找,找到第一个小于X的值,找到后把s[i]的值赋给s[j]
* @return
*/
int addjustArray(int s[],int l,int r){
int i = l, j=r;
int x = s[i];
while(i<j){
while(i<j&&s[j]>=x){
j--;
}
if(i<j){
s[i]=s[j];
i++;
}
while(i<j&&s[i]<=x){
i++;
j--;
}
if(i<j){
s[j]=s[i];
}
}
s[i]=x;
return i;
}
/**
* @param s
* @param l
* @param r
* 分治法:
* 把一个数组以某个基准数做为界线,然后把数组一分为二 ,在把两个子数组都一分为二
* 当每个子数组都为一个元素时,不能在分,递归结束
*/
void divide_and_conquer(int s[],int l,int r){
if(l<r){
int i = addjustArray(s, l, r);
addjustArray(s,l,i-1);
addjustArray(s, i+1, r);
}
}
/**
* 快速排序正是应用这种:填坑挖数+分之法的思想
* 1.选一个基准量,X=s[i]
* 2.从s[j]处开始从右往左找,找到第一个小于X的值,找到后把s[j]的值赋给s[i]
* 3.从s[i]处开始从左往右找,找到第一个小于X的值,找到后把s[i]的值赋给s[j]
*
* 然后循环调用2,3步骤
* @param s
* @param l
* @param r
*/
void quick_sort(int s[],int l,int r){
if(l<r){
int i=l;int j=r;
int x = s[l];
while(i<j){
while(i<r&&s[j]>=x){
j--;
}
if(i<j){
s[i]=s[j];
i++;
}
while(i<j&&s[i]<=x){
i++;
}
if(i<j){
s[j]=s[i];
j--;
}
}
s[i]=x;
quick_sort(s, j, i-1);
quick_sort(s, i+1, r);
}
}
}
这是直接插入排序算法,实现原理很简单,不用细讲
package com.my.lianxi;
public class InsertionSort {
/**
* @param args
* 插入排序算法(又称直接插入排序)
* 插入排序原理:
* 插入排序有点像摸牌 ,桌子上有n张牌背面朝上, 每次拿一张牌到手中, 当手中只有一张牌时它肯定
* 是手上最小的牌,当摸起第二张牌,用第二张牌和第一张比较,如果比第一张小则交换第二张牌的位置,
* 如果大于第一张牌则不交换,直接插在第一张牌的右边,当摸起第三张牌时先和前两张排好序的牌中的
* 第二张比较,如果发现比第二张小则和第二张交换位置,并继续和第一张比较,如果比第一张也小则和
* 第一张在交换位置,依次类推,当摸到第n张牌时和手上已经排好序的n-1张牌比较,找到第n张牌的
* 所需插入的位置,这样一次插入排序完成!
* @author yuzhihua
*/
public static void main(String[] args){
int a[] = {34,12,25,54,23,66,11,89,0,90};
int j=1;
while(j<10){
for(int i=j-1;i>=0;i--){
if(a[i+1]<=a[i]){
int temp=a[i];
a[i]=a[i+1];
a[i+1]=temp;
}else{
break;
}
}
j++;
}
System.out.println("输出插入排序后的数组:");
for(int i=0;i<10;i++){
System.out.print(a[i]+" ");
}
}
}