一、排序算法

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

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

  本文主要介绍选择排序、堆排序、冒泡排序、快速排序和归并排序的原理和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. U盘刻录kali linux启动盘提示找不到镜像解决方案

    选择“继续”后会来到步骤菜单,选择从shell启动,命令 df -m 查看当前磁盘挂载情况,看到  /media 目录 输入命令 umount /media 进行挂载然后输入 exit 退出

  2. 【docker学习一】CentOS7.5+Docker安装及使用「安装、查看、pull、创建、进入镜像」

    记录安装配置以及使用的过程,可能会有多处摘抄,已注明照抄地址,侵删. 是什么:个人理解,是一种移植性很强的虚拟机,支持版本控制(类似于git),同一个服务器可以运行多个docker容器,每个docke ...

  3. redhat6.0下配置DNS

    最近操作系统要结课,老师要求在redhat上配置各种服务器角色,包括dhcp.ftp.web.dns.前三个都还好,但就dns,被折磨的死去活来的,真让人头大.还好在同学的帮助下最后配置成功,实现了正 ...

  4. HDU 5775:Bubble Sort(树状数组)

    http://acm.hdu.edu.cn/showproblem.php?pid=5775 Bubble Sort Problem Description   P is a permutation ...

  5. GoLand Active Code

    56ZS5PQ1RF-eyJsaWNlbnNlSWQiOiI1NlpTNVBRMVJGIiwibGljZW5zZWVOYW1lIjoi5q2j54mI5o6I5p2DIC4iLCJhc3NpZ25lZ ...

  6. mybatis的插入与批量插入的返回ID的原理

    目录 背景 底层调用方法 单个对象插入 列表批量插入 完成 背景 最近正在整理之前基于mybatis的半ORM框架.原本的框架底层类ORM操作是通过StringBuilder的append拼接的,这次 ...

  7. http文件传输

    上传端: File uploadFile =new File(); PostMethod mPost = null; try{ String targetURL ="; HttpClient ...

  8. springboot2.0.4对接redis3.2.12版本哨兵模式

    redis 哨兵模式的创建 1. 下载redis3.2.12版本.https://codeload.github.com/antirez/redis/zip/3.2.12 2.  解压后放到/usr/ ...

  9. Xilinx ISE如何调用Modelsim进行联合仿真

    图: 在对设计的芯片进行测试时,经常要用到FPGA,可是里面的仿真工具却不如Modelsim那么好用,且在规模比较大时,ISE在仿真时,软件经常会报告内存限制的问题,此时一般会切换到Modelsim软 ...

  10. SQL Server 函数的定义及使用

    一.定义函数 1. 标量值函数: 返回一个确定类型的标量值,例如:int,char,bit等 --创建标量值函数 create function func_1(@func_parameter_1 in ...