Java实现常见的排序算法
一、排序算法
常见的排序算法主要分为下面几类:
- 选择排序
- 堆排序
- 冒泡排序
- 快速排序
- 插入排序
- 希尔排序
- 归并排序
- 桶式排序
- 基数排序
本文主要介绍选择排序、堆排序、冒泡排序、快速排序和归并排序的原理和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实现常见的排序算法的更多相关文章
- Java中常见的排序算法
这是我摘取的一段英文资料.我认为学习算法之前,对各种排序得有个大致的了解: Sorting algorithms are an important part of managing data. At ...
- java编程之常见的排序算法
java常见的排序算法 第一种:插入排序 直接插入排序 1, 直接插入排序 (1)基本思想:在要排序的一组数中,假设前面(n-1)[n>=2] 个数已经是排 好顺序的,现在要把第n个数插到前面的 ...
- java讲讲几种常见的排序算法(二)
java讲讲几种常见的排序算法(二) 目录 java讲讲几种常见的排序算法(一) java讲讲几种常见的排序算法(二) 堆排序 思路:构建一个小顶堆,小顶堆就是棵二叉树,他的左右孩子均大于他的根节点( ...
- java讲讲几种常见的排序算法
java讲讲几种常见的排序算法(一) 目录 java讲讲几种常见的排序算法(一) java讲讲几种常见的排序算法(二) 以数组array={6,3,20,8,15,1}为例 冒泡排序 思路:从第0个到 ...
- java几种常见的排序算法总结
/*************几种常见的排序算法总结***************************/ package paixu; public class PaiXu { final int ...
- Java中常见的排序方法
本博主要介绍Java中几种常见的排序算法: /* 排序方法的演示1)插入排序(直接插入排序.希尔排序)2)交换排序(冒泡排序.快速排序)3)选择排序(直接选择排序.堆排序)4)归并排序5)分配排序(基 ...
- Java实现十个经典排序算法(带动态效果图)
前言 排序算法是老生常谈的了,但是在面试中也有会被问到,例如有时候,在考察算法能力的时候,不让你写算法,就让你描述一下,某个排序算法的思想以及时间复杂度或空间复杂度.我就遇到过,直接问快排的,所以这次 ...
- 常见的排序算法总结(JavaScript)
引言 排序算法是数据结构和算法之中的基本功,无论是在笔试还是面试,还是实际运用中都有着很基础的地位.这不正直七月,每年校招的备战期,所以想把常见的排序算法记录下来.在本篇文章中的排序算法使用 Java ...
- Python全栈开发之5、几种常见的排序算法以及collections模块提供的数据结构
转载请注明出处http://www.cnblogs.com/Wxtrkbc/p/5492298.html 在面试中,经常会遇到一些考排序算法的题,在这里,我就简单了列举了几种最常见的排序算法供大家学习 ...
随机推荐
- Zookeeper详解-API(六)
ZooKeeper有一个绑定Java和C的官方API.Zookeeper社区为大多数语言(.NET,python等)提供非官方API.使用ZooKeeper API,应用程序可以连接,交互,操作数据, ...
- l论文查重平台
推荐大家一个靠谱的论文检测平台.重复的部分有详细出处以及具体修改意见,能直接在文章上做修改,全部改完一键下载就搞定了.怕麻烦的话,还能用它自带的降重功能.哦对了,他们现在正在做毕业季活动, 赠送很多免 ...
- 视频编解码的理论和实践2:Ffmpeg视频编解码
近几年,视频编解码技术在理论及应用方面都取得了重大的进展,越来越多的人想要了解编解码技术.因此,网易云信研发工程师为大家进行了归纳梳理,从理论及实践两个方面简单介绍视频编解码技术. 相关阅读推荐 &l ...
- CTF干货合集
CTF练习平台 http://hackinglab.cn/ 网络信息安全攻防学习平台 http://captf.com/ ctf题目 http://oj.xctf.org.cn/ XCTF_OJ练习平 ...
- JavaScript-倒计时效果
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- C++ 洛谷 P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm 题解
P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm 分析: 这棵树上有且仅有一个环 两种情况: 1.讨论一个点在环上,如果在则答案与它指向点相同, 2 ...
- HDU 1561:The more, The Better(有依赖的树型背包)
http://acm.hdu.edu.cn/showproblem.php?pid=1561 题意:有n个点,容量为m,每个点有一个价值,还给出n条边,代表选第i个点之前必须先选ai,问最多的价值能取 ...
- 利用Python模拟GitHub登录
最近学习了Fiddler抓包工具的简单使用,通过抓包,我们可以抓取到HTTP请求,并对其进行分析.现在我准备尝试着结合Python来模拟GitHub登录. Fiddler抓包分析 首先,我们想要模拟一 ...
- kuangbin专题 专题一 简单搜索 棋盘问题 POJ - 1321
题目链接:https://vjudge.net/problem/POJ-1321 题意:给一张棋盘,‘#’表示可以下棋的地方,‘.’表示不能下棋的地方.棋盘是n*n的,要求能放下k个棋子,要求k个棋子 ...
- 哈工大计算机网络Week3-传输层
目录 学习目标 传输层服务概述 传输层服务和协议 传输层 vs. 网络层 Internet传输层协议 多路复用和多路分用 多路复用/分用 分用如何工作? 无连接分用(UDP) 面向连接的分用 面向连接 ...