八大排序算法的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] 八大排序算法
排序有内部排序和外部排序之分,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存.我们这里说的八大排序算法均为内部排序. 下图为排序 ...
随机推荐
- 服务器(Ubuntu)远程访问ipython notebook(服务器运行ipython notebook 本地浏览器访问)
准备工作 首先要安装 ipython 推荐直接 Anaconda 搞起(装在服务器). Anaconda 帮你集成N多python相关环境(包),省得你再手动咔咔一顿安装 服务器启动ipython n ...
- TouchDelegate
TouchDelegate(Rect bounds, View delegateView) Parameters: bounds Bounds in local coordinates of the ...
- Android开发中string.xml文件的使用
为什么需要把应用中出现的文字单独存放在string.xml文中呢? 一:是为了国际化,Android建议将在屏幕上显示的文字定义在strings.xml中,如果今后需要进行国际化,比如我们开发的应用本 ...
- 创建pfx数字证书
相关参考: 安全工具: http://msdn.microsoft.com/zh-cn/library/dd233106(v=vs.110).aspx makecert: http://msdn.mi ...
- 转:探索C++0x: 1. 静态断言(static_assert)
转自:http://www.cppblog.com/thesys/articles/116985.html 简介 C++0x中引入了static_assert这个关键字,用来做编译期间的断言,因此叫做 ...
- 常用模块(random,os,json,pickle,shelve)
常用模块(random,os,json,pickle,shelve) random import random print(random.random()) # 0-1之间的小数 print(rand ...
- Delphi 正则表达式之TPerlRegEx 类的属性与方法(1): 查找
Delphi 正则表达式之TPerlRegEx 类的属性与方法(1): 查找 //查找是否存在 var reg: TPerlRegEx; begin reg := TPerlRegEx.Cre ...
- 125. Valid Palindrome(判断忽略标点的字符串是否回文,加个正则,与上一题解法一样)
Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignori ...
- 1044: [HAOI2008]木棍分割
1044: [HAOI2008]木棍分割 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2161 Solved: 779[Submit][Statu ...
- Gentoo系统安装步骤详解
下载镜像 一般我都是用国内的镜像源,不管是centos,ubuntu还是gentoo在国内的镜像来说肯定比国外快 #下载地址mirrors.163.com/gentoo/#我用的x86的http:// ...