常用排序算法

2 篇文章 0 订阅

常用的排序算法

1.排序分类
1) 插入排序(直接插入排序,希尔排序)
2) 交换排序(冒泡排序,快速排序)
3) 选择排序(直接选择排序,堆排序)
4) 归并排序
5) 分配排序(基数排序)
注释: 所需辅助空间最多:归并排序
所需辅助空间最少: 堆排序
平均速度最快: 快速排序
不稳定: 快速排序,希尔排序,堆排序

排序之间的关系: |--直接插入排序
|----插入排序--|--希尔排序
|---内部排序(只是用内存) |----选择排序--|---简单选择排序
| | |---堆排序
排序-| |----交换排序----|---冒泡排序
| |----归并排序   |--快速排序
| |----基数排序  
|---外部排序(内存和外出结合使用)


1 直接插入排序

在要排序的一组数中,假设前面(n-1)[n>=2]个数已经是拍好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是拍好顺序的,如此反复循环,直到全部拍好顺序.

Java代码实现

package dataStructureAndAlgorithm.sort;

/**
 * 插入排序
 * 		在要排序的一组数中,假设前面(n-1)[n>=2]个数已经是排好序的,现在要
 * 		把第N个数插到前面的有序数中,使得这n个数也是排好顺序。
 * @author Blossom
 *
 */
public class InsertSort {

	/**
	 * 插入排序实现
	 * @param array
	 * @return
	 * 
	 */
	public static int[] insert_sort(int[] array){
		for (int i = 0; i < array.length; i++) {
			int temp = array[i];
			int j = i - 1;
			for ( ; j >= 0 && temp < array[j]; j--) {
				array[j+1] = array[j]; //将大于temp的值向后移一位
			}
			array[j+1] = temp;
		}
		return array;
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int [] array = new int[]{49,38,65,97,76,13,27,49,78,34,12,64,5,4,62,99,98,54,56,17,18,23,34,15,35,25,53,51};
		System.out.println("array.length:" + array.length);
		System.out.print("排序之前:");
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i] + " , ");
		}
		System.out.println();
		array = insert_sort(array);
		System.out.println("array.length:" + array.length);
		System.out.print("排序之后:");
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i] + " , ");
		}
	}

}

2.希尔排序
<span style="white-space:pre">	</span>算法现将要排序的一组数按某个增量d(n/2,n为要排序数的个数)分成若干组,等组中记录的下标相差d,对每组中全部元素进行直接出肉排序,
然后再用一个较小的增量(d/2)对它进行分组,在每组中再进行直接插入排序.当增量减到1时,进行直接插入排序后,排序完成
<span style="white-space:pre">	</span>Java代码实现
<span style="white-space:pre">	</span><pre name="code" class="java">package dataStructureAndAlgorithm.sort;

/**
 * 希尔排序 算法现将排序的一组数按某个增量d(n/2,n位要排序数的个数)分成若干组,每组中记录的下标相差d,
 * 对每组中全部元素进行直接插入排序,然后再用一个较小的增量(d/2)对它进行分组,在每组在进行插入排序 。当增量减到1时,进行直接插入排序后,排序完成
 * 
 * @author Blossom
 *
 */
public class ShellSort {

	/**
	 * 希尔排序实现
	 * 
	 * @param array
	 * @return
	 */
	public static int[] shell_sort(int[] array) {

		double arrayLen = array.length;
		int temp = 0;
		while (true) {
			arrayLen = Math.ceil(arrayLen / 2);
			int len = (int) arrayLen;
			for (int i = 0; i < len; i++) {
				for (int j = i + len; j < array.length; i += len) {
					int n = j - len;
					temp = array[j];
					for (; n >= 0 && temp < array[n]; n -= len) {
						array[n + len] = array[n];
					}
					array[n + len] = temp;
				}
			}
			if (len == 1) {
				break;
			}
		}

		return array;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] array = new int[] { 1, 54, 6, 3, 78, 34, 12, 45, 56, 100 };
		System.out.print("排序之前:");
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i] + " , ");
		}
		System.out.println();
		array = shell_sort(array);
		System.out.print("排序之后:");
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i] + " , ");
		}

	}

}

 3 简单排序 

在要排序的一组数中,选出最小的一个数与第一个位置的数交换;然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止.

package dataStructureAndAlgorithm.sort;

/**
 * 简单排序
 * 		在要排序的一组数中,宣传最小的一个数与第一个位置的数交换;
 * 		然后在剩下的数当中在找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止
 * @author Blossom
 *
 */
public class SelectSort {

	/**
	 * 选择排序实现
	 * @param array
	 * @return
	 */
	public static int [] select_sort(int [] array){
		for (int i = 0; i < array.length; i++) {
			int tag = i;
			int temp = array[i];
			for (int j = i+1; j < array.length; j++) {
				if (array[j] < temp) {
					temp = array[j];
					tag = j;
				}
			}
			array[tag] = array[i];
			array[i] = temp;
		}
		return array;
	}
	
	
	public static void main(String[] args) {
		int [] array = new int []{1,54,6,3,78,34,12,45}; 
		System.out.print("排序前:");
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i] + " , ");
		}
		System.out.println();
		array = select_sort(array);
		System.out.print("排序后:");
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i] + " , ");
		}
	}
	
}

4. 堆排序

堆排序是一种树形选择排序,是对直接选择排序的有效改进。

堆的定义如下:具有n个元素的序列(h1,h2,...,hn),当且仅当满足(hi>=h2i,hi>=2i+1)或(hi<=h2i,hi<=2i+1)(i=1,2,...,n/2)时称之为堆。在这里只讨论满足前者条件的堆。由堆的定义可以看出,堆顶元素(即第一个元素)必为最大项(大顶堆)。完全二叉树可以很直观地表示堆的结构。堆顶为根,其它为左子树、右子树。初始时把要排序的数的序列看作是一棵顺序存储的二叉树,调整它们的存储序,使之成为一个堆,这时堆的根节点的数最大。然后将根节点与堆的最后一个节点交换。然后对前面(n-1)个数重新调整使之成为堆。依此类推,直到只有两个节点的堆,并对它们作交换,最后得到有n个节点的有序序列。从算法描述来看,堆排序需要两个过程,一是建立堆,二是堆顶与堆的最后一个元素交换位置。所以堆排序有两个函数组成。一是建堆的渗透函数,二是反复调用渗透函数实现排序的函数。

package dataStructureAndAlgorithm.sort;

/**
 * 堆排序 堆排序是一种树形选择排序,是对直接选择排序的有效改进
 * 定义:具有n个元素的序列(h1,h2,...hn),当且仅当满足(hi>=h2i,hi>=2i+1)或(hi<=h2i,hi<=2i+1)(i=1,2,.
 * ..,n/2) 时称之为堆。
 * 由堆的定义可以看出,堆顶元素(即第一个元素)必须为最大项。完全二叉树可以很直观的表示堆的结构,堆订为根,其它为左子树,右子树,
 * 初始时把要排序的数的序列看作是一颗顺序存储的二叉树,调整它们的存储序,使之成为一个堆,这时堆的根节点的数最大。
 * 然后将根节点与堆的最后一个节点交换。然后对前面(n-1)个数重新调整使之成为堆。依次类推,直到只有两个节点的堆,并对他们交换
 * ,最后得到n个节点的有序序列,
 * 从算法的描述来看,堆排序需要两个过程,一是建立堆,二是堆订与堆的最后一个元素交换位置。所以堆排序有两个函数组成,一是建堆的渗透函数,
 * 二是反复调用渗透函数实现排序的函数。
 * 
 * @author Blossom
 *
 */
public class HeapSort {

	// 堆排序实现
	public static int[] heap_sort(int[] array) {
		int arrayLength = array.length;
		// 循环建立堆
		for (int i = 0; i < arrayLength - 1; i++) {
			// 建立堆
			buildMaxHeap(array, arrayLength - 1 - i);
			// 交换堆顶和最后一个元素
			swap(array, 0, arrayLength - 1 - i);
		}
		return array;
	}

	private static void swap(int[] array, int i, int j) {

		int temp = array[i];
		array[i] = array[j];
		array[j] = temp;

	}

	/**
	 * 对array数组从0到i建大顶堆
	 * 
	 * @param array
	 * @param i
	 */
	private static int[] buildMaxHeap(int[] array, int i) {

		// 从i处节点(最后一个节点)的父节点开始
		for (int j = 0; j < array.length; j++) {
			// j保证正在判断的节点
			int k = i;
			// 如果当前k节点的子节点存在
			while (k * 2 + 1 <= i) {
				// k节点的左子节点的索引
				int biggerIndex = 2 * k + 1;
				// 如果biggerIndex小于i,即biggerIndex+1代表的k节点的右子节点存在
				if (biggerIndex < i) {
					// 如果右子节点的值较大
					if (array[biggerIndex] < array[biggerIndex + 1]) {
						// biggerIndex总是记录较大子节点的索引
						biggerIndex++;
					}
				}
				// 如果k节点的值小于其较大的子节点的值
				if (array[k] < array[biggerIndex]) {
					// 交换它们
					swap(array, k, biggerIndex);
					// 将biggerIndex赋予k,开始while循环的下一次循环,从新保证k节点的值大于其左右子节点的值
					k = biggerIndex;
				} else {
					break;
				}
			}
		}
		return array;
	}

	// 测试
	public static void main(String[] args) {
		int[] array = new int[] { 49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 5, 4, 62, 99, 98, 54, 56, 17, 18, 23,
				34, 15, 35, 25, 53, 51 };
		System.out.print("排序前:");
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i] + " , ");
		}
		System.out.println();
		array = heap_sort(array);
		System.out.print("排序后:");
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i] + " , ");
		}
	}

}

5 冒泡排序

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

package dataStructureAndAlgorithm.sort;


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

	/**
	 * 冒泡排序实现
	 * @param array
	 * @return
	 */
	public static int [] bubble_sort(int [] array){
		for (int i = 0; i < array.length; i++) {
			for (int j = 0; j < array.length-1-i; j++) {
				if (array[j] > array[j+1]) {
					int temp = array[j];
					array[j] = array[j+1];
					array[j+1] = temp;
				}
			}
		}
		
		return array;
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int [] array = new int []{49,38,65,97,76,13,27,49,78,34,12,64,5,4,62,99,98,54,56,17,18,23,34,15,35,25,53,51};
		System.out.print("排序前:");
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i]+" , ");
		}
		System.out.println();
		array = bubble_sort(array);
		System.out.print("排序后:");
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i]+" , ");
		}
	}

}

6 快速排序

选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分

package dataStructureAndAlgorithm.sort;


/**
 * 快速排序 选择一个季遵元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,将待排序列分成两部分,一部分
 * 比基准元素小,一部分大于等于基准元素,次数基准元素在其排好序后的正确位置,然后再用同样的方法递归的排序划分的两部分.
 * 
 * @author Blossom
 *
 */
public class QuickSort {

	public static int[] quick_sort(int[] array, int low, int high) {
		if (low < high) {
			int middle = getMiddle(array, low, high);
			quick_sort(array, low, middle - 1); // 对低字表进行递归排序
			quick_sort(array, middle + 1, high); // 对高字表进行递归排序
		}
		return array;
	}

	private static int getMiddle(int[] array, int low, int high) {

		int temp = array[low]; // 数组的第一个作为中轴
		while (low < high) {
			while (low < high && array[high] >= temp) {
				high--;
			}
			array[low] = array[high]; // 比中轴小的记录移到低端
			while (low < high && array[low] <= temp) {
				low++;
			}
			array[high] = array[low]; // 比中轴大的记录移到高端
		}
		array[low] = temp; // 中轴记录到尾

		return low; // 返回中轴位置
	}

	public static int[] sort(int[] array) {
		if (array.length > 0) {
			quick_sort(array, 0, array.length - 1);
		}
		return array;
	}

	// 测试
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] array = new int[] { 49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 5, 4, 62, 99, 98, 54, 56, 17, 18, 23,
				34, 15, 35, 25, 53, 51 };
		System.out.print("排序前:");
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i] + " , ");
		}
		System.out.println();
		array = sort(array);
		System.out.print("排序后:");
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i] + " , ");
		}
	}

}

7 归并排序

归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列

package dataStructureAndAlgorithm.sort;


/**
 * 归并排序
 * 		归并排序法是将两个(或两个以上)有序集合表合并成一个新的有序表,即把待排序序列分为若干个子序列,
 * 		每个子序列是有序的,然后在把有序子序列合并为整体有序序列
 * @author Blossom
 *
 */
public class MergeSort {

	
	/**
	 * 归并排序实现
	 * @param array
	 * @return
	 */
	public static int [] merge_sort(int [] array, int left, int right){
		if (left < right) {
			//找出中间索引
			int center = (left + right)/2;
			//对左边数组进行递归
			merge_sort(array, left, center);
			//对右边数组进行递归
			merge_sort(array, center+1, right);
			//合并数组
			array = merge(array, left, center,right);
		}
		return array;
	}
	
	private static int[] merge(int[] array, int left, int center, int right) {
		
		int [] tmpArr = new int[array.length];
		int mid = center+1;
		//third记录中间数组的索引
		int third = left;
		int temp = left;
		while(left <= center && mid <=right){
			//从两个数组中取出最小的放入中间数组
			if (array[left] <= array[mid]) {
				tmpArr[third++] = array[left++];
			}else {
				tmpArr[third++] = array[mid++];
			}
		}
		//剩余部分依次放入中间数组
		while (mid < right) {
			tmpArr[third++] = array[mid++];
		}
		while (left<=center) {
			tmpArr[third++] = array[left++];
		}
		//将中间数组的内容复制会原来的数组
		while(temp <=right){
			array[temp] = tmpArr[temp++];
		}
		return array;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int [] array = new int []{49,38,65,97,76,13,27,49,78,34,12,64,5,4,62,99,98,54,56,17,18,23,34,15,35,25,53,51};
		System.out.print("排序前:");
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i] + " , ");
		}
		array = merge_sort(array, 0, array.length-1);
		System.out.println();
		System.out.print("排序后:");
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i] + " , ");
		}
	}

}

8 基数排序

将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列

package dataStructureAndAlgorithm.sort;

import java.util.ArrayList;
import java.util.List;


/**
 * 基数排序
 * 		将所有待比较数值统一为同样的数位长度,数位较短额数前面补零,然后,从最低位开始,依次进行一次排序。
 * 		这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列
 * @author Blossom
 *
 */
public class RadixSort {

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static int[] radis_sort(int[] array){
		int max = array[0];
		for (int i = 0; i < array.length; i++) {
			if (array[i]>max) {
				max = array[i];
			}
		}
		int time = 0;
		//判断位数
		while(max>0){
			max /=10;
			time++;
		}
		//建立10个队列
		List<ArrayList> queue = new ArrayList<>();
		for(int i=0;i<10;i++){
			ArrayList<Integer> queue1 = new ArrayList<>();
			queue.add(queue1);
		}
		//进行time次分配和和收集
		for (int i = 0; i < time; i++) {
			//分配数组元素
			for (int j = 0; j < array.length; j++) {
				//得到数字的第time+1位数
				int x = array[j]%(int)Math.pow(10, i+1)/(int)Math.pow(10, i);
				ArrayList<Integer> queue2 = queue.get(x);
				queue2.add(array[j]);
				queue.set(x, queue2);
			}
			int count = 0;//元素计数器
			//收集队列元素
			for(int k=0;k<10;k++){
				while(queue.get(k).size()>0){
					ArrayList<Integer> queue3 = queue.get(k);
					array[count] = queue3.get(0);
					queue3.remove(0);
					count++;
				}
			}
		}
		return array;
	}
	
	public static void main(String[] args) {

		int [] array = new int []{49,38,65,97,76,13,27,49,78,34,12,64,5,4,62,99,98,54,101,56,17,18,23,34,15,35,25,53,51};
		System.out.print("排序前:");
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i] + " , ");
		}
		System.out.println();
		array = radis_sort(array);
		System.out.print("排序后:");
		for (int i = 0; i < array.length; i++) {
			System.out.print(array[i] + " , ");
		}
		
	}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值