八大排序算法的java实现
有时间再贴算法分析图
JDK7的Collections.sort()的算法是TimSort, 适应性的归并排序, 比较晦涩难懂, 这里没有实现
public class mySort {
// 冒泡排序
public static void myBubbleSort(int[] array) {
int lastExchange = array.length - 1; //记录最后交换位置, 避免重复比较
for (int i = lastExchange - 1; i >= 0; --i) {
for (int j = 0; j <= i; ++j) {
if (array[j] > array[j + 1]) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
lastExchange = j; //特性:最后交互位置后的元素已经有序
}
}
}
}
// 插入排序
public static void myInsertSort(int[] array) {
for (int i = 1; i <= array.length - 1; ++i) {
int temp = array[i];
int j = 0; // 给值移位并寻找插入点
for (j = i - 1; j >= 0 && array[j] > temp; --j) {
array[j + 1] = array[j];
}
array[j + 1] = temp;
}
}
// 选择排序
public static void mySelectSort(int[] array) {
for (int i = 0; i < array.length - 1; ++i) {
int minIndex = i;
// 每次选出一极值
for (int j = i + 1; j <= array.length - 1; ++j) {
if (array[j] < array[minIndex]) {
minIndex = j;
}
}
// 极值归位
if (minIndex != i) {
int temp = array[minIndex];
array[minIndex] = array[i];
array[i] = temp;
}
}
}
// 希尔排序
public static void myShellSort(int[] array) {
int gap = 5;
while (gap != 0) {
//不必刻意分组, 组1->组2->组1->组2...轮流处理
for (int j = gap; j <= array.length - 1; ++j) {
int temp = array[j];
int k = 0;
for (k = j - gap; k >= 0 && array[k] > temp; k -= gap) {
array[k + gap] = array[k];
}
array[k + gap] = temp;
}
gap /= 2; //重新分组
}
}
// 快速排序
public static void myQuickSort(int[] array) {
myQuickSortCore(array, 0, array.length - 1);
}
private static void myQuickSortCore(int[] array, int left, int right) {
if (left >= right) { //递归出口
return;
}
int mLeft = left;
int mRight = right;
int base = array[mLeft]; //第一个元素作为基准, left空位可占
while(mLeft != mRight) {
while (mRight > mLeft && array[mRight] >= base) {
--mRight;
}
array[mLeft] = array[mRight]; //right可覆盖
while (mRight > mLeft && array[mLeft] <= base) {
++mLeft;
}
array[mRight] = array[mLeft];
}
array[mRight] = base; //基准元素归位, l=r
myQuickSortCore(array, left, mLeft - 1); //递归基准以左
myQuickSortCore(array, mRight + 1 , right); //递归基准以右
}
// 归并排序
public static void myMergeSort(int[] array) {
// 每个分组中有两个来自上层迭代的有序组, gap为有序组长度, 2 * gap为分组长度
for (int gap = 1; gap < array.length; gap *= 2) {
int i = 0; // array下标
// 分组并内部排序
while (i + 2 * gap - 1 < array.length) {
mergePiece(array, i, i + gap - 1, i + 2 * gap - 1);
i += 2 * gap;
}
// 分组剩余部分排序, 只有超过一个gap才有内部排序的意义
if (i + gap - 1 < array.length) {
mergePiece(array, i, i + gap - 1, array.length - 1);
}
}
}
// 将array中有序的两段piecewise1 和 piecewise2 合并成整体有序
public static void mergePiece(int[] array, int head, int mid, int tail) {
int i = head; // piecewise1下标 [head, mid]
int j = mid + 1; // piecewise2下标 [mid + 1, tail]
// 临时数组, 保存结果
int[] arrayTemp = new int[tail - head + 1]; // combine
int k = 0; // combine下标
while (i <= mid && j <= tail) {
if (array[i] <= array[j]) {
arrayTemp[k] = array[i];
++i;
++k;
} else {
arrayTemp[k] = array[j];
++j;
++k;
}
}
// 复制多余部分 piecewise1
while (i <= mid) {
arrayTemp[k] = array[i];
++i;
++k;
}
// 复制多余部分 piecewise2
while (j <= tail) {
arrayTemp[k] = array[j];
++j;
++k;
}
// 结果复制到原始数组
k = 0;
i = head; // 重置下标, i piecewise1 + piecewise2
while (i <= tail) {
array[i] = arrayTemp[k];
++i;
++k;
}
}
// 堆排序
public static void myHeapSort(int[] array) {
// 调整堆->大顶堆
for (int i = array.length / 2 - 1; i >= 0; --i) { // 从最后非叶子节点开始
adjustHeap(array, i, array.length);
}
// 调整堆->交换堆顶/末位元素
for (int j = array.length - 1; j > 0; --j) {
int temp = array[0];
array[0] = array[j];
array[j] = temp;
adjustHeap(array, 0, j); // 只需调整堆顶父节点
}
}
// 调整为大顶堆分布, node为父节点下标, adjustLen为涉及调整的长度(为排序使用)
private static void adjustHeap(int[] array, int node, int adjustLen) {
int temp = array[node]; // 拿出node形成可占空位
for (int i = node * 2 + 1; i < adjustLen; i = node * 2 + 1) {
if (i + 1 < adjustLen && array[i] < array[i + 1]) {
++i; // 得到最大子节点
}
if (array[i] > temp) {
array[node] = array[i];
node = i; // 为下一层迭代更新父节点node, 最后为叶子
} else {
break;
}
}
array[node] = temp;
}
// 基数排序
public static void myRadixSort(int[] array) {
int d = maxBit(array);
int dec = 1; //进制迭代
final int R = 10; //桶个数
int[] tempArray = new int[array.length]; //临时数组, 代替桶存储数组, 代价是需记录下标/数量来分割桶
int[] bucketCapacity = new int[R]; //桶计数
for (int i = 1; i <= d; ++i) {
for (int j = 0; j < R; ++j) {
bucketCapacity[j] = 0; //清空桶容量
}
//计数1
for (int j = 0; j < array.length; ++j) {
int k = array[j] / dec % R;
++bucketCapacity[k];
}
//计数2 变累计, 为分割
for (int j = 1; j < R; ++j) {
bucketCapacity[j] = bucketCapacity[j - 1] + bucketCapacity[j];
}
// 存储进桶
for (int j = array.length - 1; j >= 0; --j) {
int k = array[j] / dec % R;
tempArray[bucketCapacity[k] - 1] = array[j];
--bucketCapacity[k];
}
// 写出
for(int j = 0; j < array.length; ++j) {
array[j] = tempArray[j];
}
// 下一位
dec *= 10;
}
}
//求数组元素的最大位数
private static int maxBit(int[] array) {
int bit = 1;
int dec = 10;
for (int i = 0; i < array.length; ++i) {
while (array[i] >= dec) {
++bit;
dec *= 10;
}
}
return bit;
}
}
八大排序算法的java实现的更多相关文章
- 八大排序算法的Java代码实现
简单插入排序 public class QuickSort { private static void quickSort(int [] a, int low, int high){ if (low ...
- 八大排序算法Java实现
本文对常见的排序算法进行了总结. 常见排序算法如下: 直接插入排序 希尔排序 简单选择排序 堆排序 冒泡排序 快速排序 归并排序 基数排序 它们都属于内部排序,也就是只考虑数据量较小仅需要使用内存的排 ...
- 八大排序算法详解(动图演示 思路分析 实例代码java 复杂度分析 适用场景)
一.分类 1.内部排序和外部排序 内部排序:待排序记录存放在计算机随机存储器中(说简单点,就是内存)进行的排序过程. 外部排序:待排序记录的数量很大,以致于内存不能一次容纳全部记录,所以在排序过程中需 ...
- Java八大排序算法
Java八大排序算法: package sort; import java.util.ArrayList; import java.util.Arrays; import java.util.List ...
- 八大排序算法总结与java实现(转)
八大排序算法总结与Java实现 原文链接: 八大排序算法总结与java实现 - iTimeTraveler 概述 直接插入排序 希尔排序 简单选择排序 堆排序 冒泡排序 快速排序 归并排序 基数排序 ...
- 八大排序算法 JAVA实现 亲自测试 可用!
今天很高兴 终于系统的实现了八大排序算法!不说了 直接上代码 !代码都是自己敲的, 亲测可用没有问题! 另:说一下什么是八大排序算法: 插入排序 希尔排序 选择排序 堆排序 冒泡排序 快速排序 归并排 ...
- 常见排序算法(附java代码)
常见排序算法与java实现 一.选择排序(SelectSort) 基本原理:对于给定的一组记录,经过第一轮比较后得到最小的记录,然后将该记录与第一个记录的位置进行交换:接着对不包括第一个记录以外的其他 ...
- 几大排序算法的Java实现
很多的面试题都问到了排序算法,中间的算法和思想比较重要,这边我选择了5种常用排序算法并用Java进行了实现.自己写一个模板已防以后面试用到.大家可以看过算法之后,自己去实现一下. 1.冒泡排序:大数向 ...
- [Data Structure & Algorithm] 八大排序算法
排序有内部排序和外部排序之分,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存.我们这里说的八大排序算法均为内部排序. 下图为排序 ...
随机推荐
- win64系统丢失d3dx9d_40.dll问题
在Win64系统中,安装了DXSDK.DX9,却一直显示如上对话框,导致程序运行不起来. 于是我在网上找到了一个d3dx9d_40.dll,覆盖到C:\Windows\System32中,但是问题依然 ...
- [译]理解Windows消息循环
出处:http://www.cnblogs.com/zxjay/archive/2009/06/27/1512372.html 理解消息循环和整个消息传送机制对Windows编程来说非常重要.如果对消 ...
- python16_day05【迭代器、生成器、模块】
一.列表生成式 1.我现在有个需求,看列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],我要求你把列表里的每个值加1,你怎么实现?你可能会想到2种方式 : >>> a ...
- 简单的menu和点击(包括alertDialog定制)
import android.app.Activity;import android.app.AlertDialog;import android.app.Dialog;import android. ...
- HDU - 6430 Problem E. TeaTree 2018 Multi-University Training Contest 10 (LCA+枚举因子)
题意:一棵树,每个点都有自己val(1 <= val <= 1e5),而任意两个点u,v可以对lca(u,v) 产生gcd(valu,valv)的贡献,求每个点能接受到来自子树贡献的最大值 ...
- hadoop13---centos安装jdk
由于各Linux开发厂商的不同,因此不同开发厂商的Linux版本操作细节也不一样,今天就来说一下CentOS下JDK的安装: 方法一:手动解压JDK的压缩包,然后设置环境变量 1.在/usr/目录下创 ...
- jQuery多级联动美化版Select下拉框
在线演示 本地下载
- redis安装优化:
1)内存分配控制: vm.overcommit_memoryredis启动时肯呢个会出现这样的日志: :M Apr ::! Background save may fail under low mem ...
- 会话控制Session的应用
Session技术与Cookie相似,都是用来存储使用者的相关资料.但是最大不同之处在于Cookie是将数据存放于客户端计算机中,而Session则是将数据存放于服务器系统下. 在Web技术发展史上, ...
- Linux下挂载windows的共享文件夹
环境说明: 由于领导要求:现需要将某Linux服务器下的一个文件移动到某windows服务器下(服务器均在机房托管,要远程操作) 由于操作为一次性,则决定在windows下建立一个共享文件夹,linu ...