您的位置:首页 > 其它

经典排序算法之冒泡、选择和插入排序

2017-05-10 16:53 525 查看
排序算法学了好久了,今天再来复习一下。毕竟是很经典的排序算法。

1 冒泡排序

算法描述

  设待排序记录序列中的记录个数为n
  一般地,第i趟起泡排序从1到n-i+1
  依次比较相邻两个记录的关键字,如果发生逆序,则交换之。
  其结果是这n-i+1个记录中,关键字最大的记录被交换到第n-i+1的位置上,最多作n-1趟。

算法实现:

package cn.hncu.sortAlgorithm;

public class SortMethods1 {
/*
* 算法好坏的评价指标:
* 1.时间复杂度,就是算法运行的快慢(时间)-----通常用计算机的运算(算术,赋值)次数来代替
* 2.空间复杂度,占用内存空间的大小------通常用程序中使用了多少变量(栈内存,堆内存),这些变量总共占了多少内存
*/
public static void main(String[] args) {
int a[]={5,8,-3,11,7,28,95,-12,8};//8个数
//1.冒泡排序
//1.1普通的冒泡排序
//bubbleSort(a);
//1.2带优化的冒泡排序
bubbleSort2(a);
}
//1.1普通的冒泡排序
private static void bubbleSort(int[] a) {
for(int i=0;i<a.length-1;i++){//趟数:n-1
for(int j=0;j<a.length-i-1;j++){//让第j个和第j+1个数进行比较,违反需求则交换。j:0->j:n-i-1
if(a[j]>a[j+1]){
swap(a,j,j+1);
}
}
}
}

//1.2 冒泡排序(优化)----只要发现一趟走下来没有一次交换那么就认为已经排好序,后面的数就无需再遍历了
private static void bubbleSort2(int[] a) {
for(int i=0;i<a.length-1;i++){
boolean isOk=true;
for(int j=0;j<a.length-i-1;j++){
if(a[j]>a[j+1]){
swap(a,j,j+1);
isOk=false;
}
}
if(isOk) break;
}
}

算法评价



2 选择排序

算法描述

  首先通过n-1次比较,从n个数中找出最小的,将它与第一个数交换——第一趟选择排序,结果最小的数被安置在第一个元素位置上。
  再通过n-2次比较,从剩余的n-1个数中找出关键字次小的记录,将它与第二个数交换——第二趟选择排序。
  重复上述过程,共经过n-1趟排序后,排序结束。

算法实现:

//2.选择排序
//2.1 选择排序的类似思维但性能不好----例如排手机
//selectSort0(a);
//2.2 真正的选择排序
selectSort(a);
//2.1 选择排序的类似思维但性能不好
private static void selectSort0(int[] a) {
for(int i=0;i<a.length-1;i++){
for(int j=i+1;j<a.length;j++){
if(a[i]>a[j]){
swap(a,i,j);
}
}
}
}
//2.2 选择排序
private static void selectSort(int[] a) {
for(int i=0;i<a.length-1;i++){
int k=i;
for(int j=i+1;j<a.length;j++){
if(a[k]>a[j]) k=j; //要用a[k]和a[j]依次作比较,找出最小的那个
}
//经过上面的循环,第k个元素一定是当前(从第i个元素到最后这些元素中)最小的
if(i!=k) swap(a,i,k);
}
}


算法评价



3 插入排序

算法描述:

  记录存放在数组R[0….n-1]中,排序过程的某一中间时刻,R被划分成两个子区间R[0…i-1]和R[i….n-1],其中:前一个子区间是已排好序的有序区;后一个子区间则是当前未排序的部分。

基本操作:

  将当前无序区的第1个记录R[i]插入到有序区R[0….i-1]中适当的位置,使R[0…i]变为新的有序区。

操作细节:

  当插入第i(i≥1)个对象时, 前面的r[0], r[1], …, r[i-1]已经排好序。

  用r[i]的关键字与r[i-1],r[i-2], …的关键字顺序进行比较(和顺序查找类似),如果小于,则将r[x]向后移动(插入位置后的记录向后顺移);找到插入位置即将r[i]插入。

算法实现:

//3. 插入排序
//3.1 简单插入排序
//insertSort(a);
// 3.1 简单插入排序
private static void insertSort(int[] a) {
//依次把每个元素拿来插入到有序序列当中(从第二个开始,到最后就行)
for(int i=0;i<a.length-1;i++){
//待插入的数
int temp=a[i+1];

//下面的这一段是决定temp所在的位置(j+1)以及 让比temp大的数往后挪动一个位置
int j=i;
//System.out.println(a[j]+".."+temp+".."+a[temp]);
while(a[j]>temp){//如果有序数列中 第j位置的数 比待插入的数 大,则把a[j]往后挪动一个位置
a[j+1]=a[j];// a[j] 挪到了a[j+1]的位置
j--;
if(j<0) break;
}
//这样找出来的第a[j]数是比temp小的数,所以让temp坐在第j个数的后一个位置:即j+1
a[j+1]=temp;
}
}

3.2 二分插入排序(直接插入排序的优化)

算法描述:

  在直接插入排序的基础上,利用二分(折半)查找算法决策出当前元素所要插入的位置。

    二分查找:找到中间元素,如果中间元素比当前元素大,则当前元素要插入到中间元素的左侧;否则,中间元素比当前元素小,则当前元素要插入到中间元素的右侧。

  找到当前元素的插入位置i之后,把i和high之间的元素从后往前依次后移一个位置,然后再把当前元素放入位置i。

算法实现:

//3.2 加入二分查找的插入排序 //注:二分查找的前提要有序
binaryInsertSort(a);
//3.2 加入二分查找的插入排序
private static void binaryInsertSort(int[] a) {
for(int i=0;i<a.length-1;i++){
int temp=a[i+1];

//用二分查找决定插入的位置
int low=0;
int high=i;
while(low<=high){
int mid=(low+high)/2;
//用中间位置元素和当前待插入的数(temp)作比较
if(a[mid]>temp)//落在左半区
high=mid-1;
else
low=mid+1;
}
//上面这段只是找到插入位置

//移位:把待插入位置腾出来
for(int j=i;j>high;j--){
a[j+1]=a[j];
}
//让temp坐在a[high+1]的位置上或者a[low]的位置上
a[low]=temp;
}
}

亲测都是可以排序成功的哦。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐