一、排序算法

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

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

  本文主要介绍选择排序、堆排序、冒泡排序、快速排序和归并排序的原理和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. 【转】Linux下添加FTP账号和服务器、增加密码和用户,更改FTP目录

    转自:http://blog.csdn.net/cloudday/article/details/8640234   1. 启动VSFTP服务器 A:cenos下运行:yum  install  vs ...

  2. 网络学习笔记(三):HTTP缓存

      HTTP缓存是一种保存资源副本并在下次请求时直接使用该副本的技术,合理的使用缓存可以有效的提升web性能.   浏览器将js文件.css文件.图片等资源缓存,当下次请求这些资源时,可以不发送网络请 ...

  3. 如何把设计稿中px值转化为想要的rem值

    首先我们需要的是把尺寸转化为rem值 假如 设计稿中的是 200px*200px的图片 移动端的设计图尺寸一般是640*750; 第一步.  把图片分为若干份(好算即可),每一份的大小就是rem的单位 ...

  4. Python笔记【1】_字符串学习

    #!/usr/bin/env/python #-*-coding:utf-8-*- #Author:LingChongShi #查看源码Ctrl+左键 #字符串:通常有单引号“'”.双引号“" ...

  5. Method com/mysql/jdbc/PreparedStatement.isClosed()Z is abstract 报错解决

    java.lang.AbstractMethodError: Method com/mysql/jdbc/PreparedStatement.isClosed()Z is abstract ----- ...

  6. 【HDU - 2102】A计划(bfs)

    -->A计划 Descriptions: 可怜的公主在一次次被魔王掳走一次次被骑士们救回来之后,而今,不幸的她再一次面临生命的考验.魔王已经发出消息说将在T时刻吃掉公主,因为他听信谣言说吃公主的 ...

  7. Requests方法 -- cookie绕过验证码登录操作

    前言有些登录的接口会有验证码:短信验证码,图形验证码等,这种登录的话验证码参数可以从后台获取的(或者查数据库最直接).获取不到也没关系,可以通过添加 cookie 的方式绕过验证码. 1.这里以登录博 ...

  8. 1.谈谈对Java平台的理解

    1.谈谈你对Java平台的理解 Java 本身是一种面向对象的语言,最显著的特性有两个方面,一是所谓的“一次编译,到处运行”(Compile once,run anywhere),能够非常容易地获取跨 ...

  9. 如何在VPS上搭建WordPress博客网站(史上最全图文教程)

    由于现在很多人仍然使用共享主机,所以我决定写这篇教程,教你如何设置自己的虚拟专用服务器(VPS),以便为启动一个 WordPress 网站准备好所有必要的服务. 为什么共享托管不是最好的选择? 你的 ...

  10. C++ 洛谷 P1879 [USACO06NOV]玉米田Corn Fields

    没学状压DP的看一下 合法布阵问题  P1879 [USACO06NOV]玉米田Corn Fields 题意:给出一个n行m列的草地(n,m<=12),1表示肥沃,0表示贫瘠,现在要把一些牛放在 ...