排序算法

1、 插入排序

插入排序就是把当前待排序的元素插入到一个己经排好序的列表里面

基本思想:

将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表。即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止。

要点:设立哨兵,作为临时存储和判断数组边界之用。

直接插入排序示例:



如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。

package com.sort;
//插入排序
public class Test03 {
	public static void main(String[] args){
		int[] n = {1,2,4,6,8,3,5,43,76,43,23,89,65};
		Sort(n);
		for (int i = 0; i < n.length; i++) {
			System.out.print(n[i] + "  ");
		}
	}
	public static void Sort(int[] array){
		if(array==null || array.length<2){
			return;
		}
		for(int i=1;i<array.length;i++){
			int copy = array[i];//设置一个待排序值的拷贝
			int pos=i;
			for(int j=i-1;j>=0;j--){
				if(array[j]>copy){
					array[j+1]=array[j];
					pos-=1;
				}else{
					return;
				}
			}
			array[pos]=copy;
		}
	}
}


2. 插入排序—希尔排序(Shell`s Sort)

希尔排序是1959 年由D.L.Shell 提出来的,相对直接排序有较大的改进。希尔排序又叫缩小增量排序

基本思想:

先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。

操作方法:

  1. 选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;
  2. 按增量序列个数k,对序列进行k 趟排序;
  3. 每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

希尔排序的示例:


算法实现:

 

我们简单处理增量序列:增量序列d = {n/2 ,n/4, n/8 .....1} n为要排序数的个数

即:先将要排序的一组记录按某个增量dn/2,n为要排序数的个数)分成若干组子序列,每组中记录的下标相差d.对每组中全部元素进行直接插入排序,然后再用一个较小的增量(d/2)对它进行分组,在每组中再进行直接插入排序。继续不断缩小增量直至为1,最后使用直接插入排序完成排序。

package com.sort;
/**希尔排序的原理:根据需求,如果你想要结果从大到小排列,它会首先将数组进行分组,然后将较大值移到前面,较小值 
 * 移到后面,最后将整个数组进行插入排序,这样比起一开始就用插入排序减少了数据交换和移动的次数,可以说希尔排序是加强 
 * 版的插入排序 
 * 拿数组5, 2, 8, 9, 1, 3,4来说,数组长度为7,当increment为3时,数组分为两个序列 
 * 5,2,8和9,1,3,4,第一次排序,9和5比较,1和2比较,3和8比较,4和比其下标值小increment的数组值相比较 
 * 此例子是按照从大到小排列,所以大的会排在前面,第一次排序后数组为9, 2, 8, 5, 1, 3,4 
 * 第一次后increment的值变为3/2=1,此时对数组进行插入排序, 
 */  
public class Sort02 {
	public static void Sort02(int[] data){
		int temp=0;
		int j=0;
		for(int incream=data.length/2;incream>0;incream/=2){
			for(int i=incream;i<data.length;i++){
				temp=data[i];
				for(j=i;j>=incream;j-=incream){
					if(temp>data[j-incream]){
						data[j]=data[j-incream];
					}else{
						break;
					}
				}
				data[j]=temp;
			}
		}
	}
	public static void main(String args[]) {
		int[] data = new int[] { 5, 2, 8, 9, 1, 3, 4 };

		System.out.println("未排序前");
		for (int i = 0; i < data.length; i++) {
			System.out.print(data[i] + " ");
		}

		Sort02(data);

		System.out.println("\n排序后");
		for (int i = 0; i < data.length; i++)
			System.out.print(data[i] + " ");
	}
}

3. 选择排序—简单选择排序(Simple Selection Sort)

基本思想:

在要排序的一组数中,选出最小(或者最大)的个数与第1个位置的数交换;然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后个数)比较为止。

简单选择排序的示例:

 

操作方法:

第一趟,从n 个记录中找出关键码最小的记录与第一个记录交换;

第二趟,从第二个记录开始的n-1 个记录中再选出关键码最小的记录与第二个记录交换;

以此类推.....

第i 趟,则从第i 个记录开始的n-i+1 个记录中选出关键码最小的记录与第i 个记录交换,

直到整个序列按关键码有序。


算法实现:


package com.sort;

public class ChooseSort {
	public static void fun(int[] a) {
		if (a == null || a.length <= 0) {
			return;
		}
		for (int i = 0; i < a.length; i++) {
			int min = i; /* 将当前下标定义为最小值下标 */

			for (int j = i + 1; j < a.length; j++) {
				if (a[min] > a[j]) { /* 如果有小于当前最小值的关键字 */
					min = j; /* 将此关键字的下标赋值给min */
				}
			}
			if (i != min) {/* 若min不等于i,说明找到最小值,交换 */
				int tmp = a[min];
				a[min] = a[i];
				a[i] = tmp;
			}
		}
	}

	public static void main(String args[]) {
		int[] array = { 43, 23, 1, 2, 6, 4, 32, 9, 32 };
		fun(array);
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i] + "   ");
		}
	}
}

简单选择排序的改进——二元选择排序

简单选择排序,每趟循环只能确定一个元素排序后的定位。我们可以考虑改进为每趟循环确定两个元素(当前趟最大和最小记录)的位置,从而减少排序所需的循环次数。改进后对n个数据进行排序,最多只需进行[n/2]趟循环即可。具体实现如下:


package com.sort;

public class SelectionSort3 {
	public static void main(String[] args) {
		int[] a = { 14, 144, 43, 34, 23 };
		selectTwoSort(a, a.length);

		for (int i = 0; i < a.length; i++) {
			System.out.print(a[i] + "  ");
		}
	}

	public static void selectTwoSort(int a[], int n) {
		int i;
		for (i = 0; i <= n / 2; i++) { // i从0开始,不然第一个数据,就没有参与比较
			int min = i;
			int max = n - i - 1;// 最大数据指针应该这么设置吧!
			int tmp = 0;
			int j;
			for (j = i + 1; j < n - i - 1; j++) {
				if (a[j] < a[min]) {
					min = j;
					continue;
				}
				if (a[j] > a[max]) {
					max = j;
				}
			}
			// 放置最小值
			tmp = a[min];
			a[min] = a[i];
			a[i] = tmp;
			// 放置最大值
			tmp = a[max];
			a[max] = a[n - i - 1];
			a[n - i - 1] = tmp;
		}
	}
}


4. 交换排序—冒泡排序(Bubble Sort)

基本思想:

在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。

冒泡排序的示例:

 

package com.sort;
//冒泡排序
public class Sort03 {
	public static void main(String[] args) {
		int[] a = { 14, 144, 43, 34, 23 };
		fun(a, a.length);

		for (int i = 0; i < a.length; i++) {
			System.out.print(a[i] + "  ");
		}
	}
	public static void fun(int[]a,int n){
		for(int i=0;i<a.length-1;i++){
			for(int j=0;j<a.length-1-i;j++){
				if(a[j]>a[j+1]){
					int temp = a[j];
					a[j]=a[j+1];
					a[j+1]=temp;
				}
			}
		}
	}
	
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值