一、排序算法

  常见的排序算法主要分为下面几类:

    • 选择排序
    • 堆排序
    • 冒泡排序
    • 快速排序
    • 插入排序
    • 希尔排序
    • 归并排序
    • 桶式排序
    • 基数排序

  本文主要介绍选择排序、堆排序、冒泡排序、快速排序和归并排序的原理和Java代码实现。

二、算法实现

2.1 选择排序

  选择排序的原理:

    选择排序是一种简单直观的排序算法,它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

Java实现:

    public static void selSort(int a[]){
if(a==null||a.length==0){
return;
}
for (int i = 0; i < a.length; i++) {
int tmp = a[i];//存储遍历时最小的值
int flag = i;//存储最小值的位置
for(int j = i+1;j<a.length;j++){
if(a[j]<tmp){
//找到更小的值,将值和位置存储起来
tmp = a[j];
flag = j;
}
}
int tmp2 = a[i];//临时保存a[i]的值,用于交换值得位置
a[i] = tmp;
a[flag] = tmp2;
}
}

2.2 堆排序

  堆排序的原理:

  堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序。堆是具有以下性质的完全二叉树:

  • 每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;
  • 每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。
  • 完全二叉树: 除了最后一层之外的其他每一层都被完全填充,并且所有结点都保持向左对齐

  它的基本思想是将待排序的序列构造成一个大顶堆(或小顶堆)。此时,整个序列的最大值就是堆顶的根节点,将其与堆数组的末尾元素交换,此时末尾元素就是最大值,然后将剩余的 n-1 个序列重新构造成一个最大堆,再将新的最大堆的顶与末尾元素交换,如此反复执行,便能得到一个有序序列了。

Java实现

public static void heapSort(int[] arr){
buildMaxHeap(arr);
int heapSize = arr.length;
//最大值的节点与最后一个节点交换位置
for (int i = arr.length - 1; i > 0; i--) {
int temp = arr[i];
arr[i] = arr[0];
arr[0] = temp;
//最后一个节点为最大值后,再对前边节点进行堆排序,每交换出一个最大值,最大堆的大小减1
heapSize--;
maxHeapify(arr, 0, heapSize);
}
}
/**
* 4 3 9 5 10 2 6
* 0 1 2 3 4 5 6
*
* 4
* 3 9
* 5 10 2 6
*
* @param arr 待排序的数组
* @param index 要进行调整的节点位置
* @param heapSize 最大堆的大小
*/
public static void maxHeapify(int[] arr, int index, int heapSize) {
int leftIndex = 2 * index + 1;//左节点
int rightIndex = 2 * index + 2;
int largeIndex;//临时存储三个节点中最大的节点
if (leftIndex < heapSize && arr[leftIndex] > arr[index]) {
largeIndex = leftIndex;
} else {
largeIndex = index;
}
if (rightIndex < heapSize && arr[rightIndex] > arr[largeIndex]) {
largeIndex = rightIndex;
}
if (largeIndex != index) {
//与最大值的节点交换位置
int temp = arr[largeIndex];
arr[largeIndex] = arr[index];
arr[index] = temp;
//递归的方式对新的节点进行最大堆调整
maxHeapify(arr, largeIndex, heapSize);
}
}
//建立最大堆,遍历其中的非叶子节点,调整位置,达到最大堆的特点,即父节点的值大于子节点的值
public static void buildMaxHeap(int[] arr) {
int heapSize = arr.length;
for (int i = (arr.length - 2) / 2; i > -1; i--) {
maxHeapify(arr, i, heapSize);
}
}

2.3 冒泡排序

  冒泡排序的原理:

  冒泡排序需要重复地走访要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,该数列就已经排序完成。

步骤如下所示:

      • 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
      • 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
      • 针对所有的元素重复以上的步骤,除了最后一个。
      • 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

Java实现

/**
* 冒泡排序
* 每次选择两个相邻的值进行比较,较小的放在前面
* 第一轮比较时,第一个和第二个比较,第二个和第三个比较,一直到最后一个
* 第一轮结束,最后一个值为最大值
* 再进行第二轮比较,比较时,无需再比较最后一个值
* ...
* 依次类推,保证每一轮的最后一个值都是最大值,直到没有值再与第一个值比较时,循环结束
* @param a
*/
public static void bubSort(int a[]){
for(int i=0; i<a.length; i++){
//第一轮比较完后,最后一个位置的值为最大值
//每遍历一轮,最后的位置就能多确定一个
for(int j=0; j<a.length-i-1; j++){
int tmp = a[j];//保存a[j]的值,如果比下一个值大,则交换位置
if(a[j]>a[j+1]){
a[j] = a[j+1];
a[j+1] = tmp;
}
}
}
}

2.4 快速排序

快速排序的原理: 

  快速排序采用了分治的思想,将一个数组分成多个子数组,当子数组满足排序时,整个数组则已经排好序。它的基本思想是通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

Java实现

/**
* 快速排序
* 选择一个基准值,将比其小的值放在左边,比其大的值放在右边
* 对新产生的数组左边和右边再递归以上动作
* 直到所有子数组都已排好序
* @param array 数组
* @param start 开始节点
* @param end 最后节点
*/
public static void quiSort(int[] array, int start, int end) {
if (start < end) {
//递归遍历
int position = partition(array, start, end);
quiSort(array, start, position - 1);
quiSort(array, position + 1, end);
}
}
public static int partition(int[] array, int start, int end) {
int position = start - 1;//开始时start前一个位置
int base = array[end];//选择最后一个元素为基准
for (int i = start; i < end; i++) {
//从开始节点遍历
if (array[i] <= base) {
position++;
//第i个元素和position位置元素交换位置
int temp = array[position];
array[position] = array[i];
array[i] = temp;
}
}
//最后一个元素与position交换位置
int temp = array[position + 1];
array[position + 1] = array[end];
array[end] = temp;
//返回基准所在的位置
return position + 1;
}

2.5 归并排序

归并排序的原理:

  归并排序利用的是分治的思想实现的,对于给定的一组数据,利用递归与分治技术将数据序列划分成为越来越小的子序列,之后对子序列排序,最后再用递归方法将排好序的子序列合并成为有序序列。合并两个子序列时,需要申请两个子序列加起来长度的内存,临时存储新的生成序列,再将新生成的序列赋值到原数组相应的位置。

Java实现

public static void merSort(int[] arr,int left,int right){
if(left<right){
int mid = (left+right)/2;
merSort(arr,left,mid);//左边归并排序,使得左子序列有序
merSort(arr,mid+1,right);//右边归并排序,使得右子序列有序
merge(arr,left,mid,right);//合并两个子序列
}
}
private static void merge(int[] arr, int left, int mid, int right) {
int[] temp = new int[right - left + 1];//ps:也可以从开始就申请一个与原数组大小相同的数组,因为重复new数组会频繁申请内存
int i = left;
int j = mid+1;
int k = 0;
while(i<=mid&&j<=right){
if (arr[i] < arr[j]) {
temp[k++] = arr[i++];
} else {
temp[k++] = arr[j++];
}
}
while(i<=mid){//将左边剩余元素填充进temp中
temp[k++] = arr[i++];
}
while(j<=right){//将右序列剩余元素填充进temp中
temp[k++] = arr[j++];
}
//将temp中的元素全部拷贝到原数组中
for (int k2 = 0; k2 < temp.length; k2++) {
arr[k2 + left] = temp[k2];
}
}

Java实现常见的排序算法的更多相关文章

  1. Java中常见的排序算法

    这是我摘取的一段英文资料.我认为学习算法之前,对各种排序得有个大致的了解: Sorting algorithms are an important part of managing data. At ...

  2. java编程之常见的排序算法

    java常见的排序算法 第一种:插入排序 直接插入排序 1, 直接插入排序 (1)基本思想:在要排序的一组数中,假设前面(n-1)[n>=2] 个数已经是排 好顺序的,现在要把第n个数插到前面的 ...

  3. java讲讲几种常见的排序算法(二)

    java讲讲几种常见的排序算法(二) 目录 java讲讲几种常见的排序算法(一) java讲讲几种常见的排序算法(二) 堆排序 思路:构建一个小顶堆,小顶堆就是棵二叉树,他的左右孩子均大于他的根节点( ...

  4. java讲讲几种常见的排序算法

    java讲讲几种常见的排序算法(一) 目录 java讲讲几种常见的排序算法(一) java讲讲几种常见的排序算法(二) 以数组array={6,3,20,8,15,1}为例 冒泡排序 思路:从第0个到 ...

  5. java几种常见的排序算法总结

    /*************几种常见的排序算法总结***************************/ package paixu; public class PaiXu { final int  ...

  6. Java中常见的排序方法

    本博主要介绍Java中几种常见的排序算法: /* 排序方法的演示1)插入排序(直接插入排序.希尔排序)2)交换排序(冒泡排序.快速排序)3)选择排序(直接选择排序.堆排序)4)归并排序5)分配排序(基 ...

  7. Java实现十个经典排序算法(带动态效果图)

    前言 排序算法是老生常谈的了,但是在面试中也有会被问到,例如有时候,在考察算法能力的时候,不让你写算法,就让你描述一下,某个排序算法的思想以及时间复杂度或空间复杂度.我就遇到过,直接问快排的,所以这次 ...

  8. 常见的排序算法总结(JavaScript)

    引言 排序算法是数据结构和算法之中的基本功,无论是在笔试还是面试,还是实际运用中都有着很基础的地位.这不正直七月,每年校招的备战期,所以想把常见的排序算法记录下来.在本篇文章中的排序算法使用 Java ...

  9. Python全栈开发之5、几种常见的排序算法以及collections模块提供的数据结构

    转载请注明出处http://www.cnblogs.com/Wxtrkbc/p/5492298.html 在面试中,经常会遇到一些考排序算法的题,在这里,我就简单了列举了几种最常见的排序算法供大家学习 ...

随机推荐

  1. JavaWEB路径总结

    这篇文章是小编一直想写的一篇,主要是对web阶段中各个路径进行的一些总结,希望读者看过之后对于路径方面有一个清晰的认识.首先声明一点:世界上一切东西都是相对的,对于这点而言,相信大家并不陌生,从初中开 ...

  2. Spring事务原理一探

    概括来讲,事务是一个由有限操作集合组成的逻辑单元.事务操作包含两个目的,数据 一致以及操作隔离.数据一致是指事务提交时保证事务内的所有操作都成功完成,并且 更改永久生效:事务回滚时,保证能够恢复到事务 ...

  3. Spring 5.x 、Spring Boot 2.x 、Spring Cloud 与常用技术栈整合

    项目 GitHub 地址:https://github.com/heibaiying/spring-samples-for-all 版本说明: Spring: 5.1.3.RELEASE Spring ...

  4. 【设计模式】行为型08状态模式(status Pattern)

    状态模式(status Pattern)       定义:允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类.其别名为状态对象(Objects for States).与命令模式 ...

  5. python面试题(三)列表操作

    接上一篇............. 0x01:列表的去重操作 al = [1, 1, 2, 3, 1, 2, 4] #set方法元素去重 al_set = set(al) print(list(al_ ...

  6. Excel导出打印失败报错 (eg HSSF instead of XSSF)

    错误信息: java.lang.RuntimeException: org.apache.poi.openxml4j.exceptions.OLE2NotOfficeXmlFileException: ...

  7. 100天搞定机器学习|Day2简单线性回归分析

    第一天机器学习100天|Day1数据预处理,我们学习了数据预处理.知道了,数据预处理是机器学习中最基础和最麻烦,未来占用时间最长的一步操作.数据预处理一般有六个步骤,导入库.导入数据集.处理缺失值.分 ...

  8. C++学习书籍推荐《Exceptional C++(英文)》下载

    百度云及其他网盘下载地址:点我 作者简介 Herb Sutter is the author of three highly acclaimed books, Exceptional C++ Styl ...

  9. C语言学习书籍推荐《C陷阱与缺陷》下载

    下载地址:点我 凯尼格 (作者), 高巍 (译者) <C和C++经典著作:C陷阱与缺陷>适合有一定经验的C程序员阅读学习,即便你是C编程高手,<C和C++经典著作:C陷阱与缺陷> ...

  10. NioEventLoopGroup初始化

    本文是我对Netty的NioEventLoopGroup及NioEventLoop初始化工作的源码阅读笔记, 如下图,是Netty的Reactor线程模型图,本文描述NioEventLoopGroup ...