8种排序算法 Java实现
冒泡排序 O(n2)
两个数比较大小,较大的数下沉,较小的数冒起来。
public static void bubbleSort(int[] a) {
//临时变量
int temp;
//i是循环次数,也是冒泡的结果位置下标,5个数组循环5次
for (int i = 0; i < a.length; i++) {
//从最后向前面两两对比,j是比较中下标大的值
for (int j = a.length - 1; j > i; j--) {
//让小的数字排在前面
if (a[j] < a[j - 1]) {
temp = a[j];
a[j] = a[j - 1];
a[j - 1] = temp;
}
}
}
}
选择排序 O(n2)
在长度为N的无序数组中,第一次遍历n-1个数,找到最小的数值与第一个元素交换;
第二次遍历n-2个数,找到最小的数值与第二个元素交换;
。。。
第n-1次遍历,找到最小的数值与第n-1个元素交换,排序完成。
public static void selectSort(int[] a) {
//临时变量
int temp;
//i是循环次数,也是选择交换的结果的位置下标,5个数组循环5次
for (int i = 0; i < a.length; i++) {
//最小值下标
int min = i;
for (int j = i + 1; j < a.length; j++) {
if (a[min] > a[j]) {
min = j;
}
}
temp = a[i];
a[i] = a[min];
a[min] = temp;
}
}
插入排序 O(n2)
在要排序的一组数中,假定前n-1个数已经排好序,现在将第n个数插到前面的有序数列中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。
public static void insertSort(int[] a) {
int temp;
//i是循环次数,也是插入的队列的长度,最后一位是a[i]
//所以一开始a[0]是排好的一个队列,比较a.length-1次,最后一次循环是a[a.length-1]插入a[0]~a[a.length-2]
for (int i = 0; i < a.length - 1; i++) {
//a[j]是要插入的数字,从a[j]往a[0]比较
for (int j = i + 1; j > 0; j--) {
//如果插入的数小,交换位置
if (a[j] < a[j - 1]) {
temp = a[j];
a[j] = a[j - 1];
a[j - 1] = temp;
} else {
//因为默认a[0]~a[i]是排好的,a[i+1]比a[i]大的话,就不用比较后面了
break;
}
}
}
}
希尔排序 O(n1.5)
在要排序的一组数中,根据某一增量分为若干子序列,并对子序列分别进行插入排序。
然后逐渐将增量减小,并重复上述过程。直至增量为1,此时数据序列基本有序,最后进行插入排序。
public static void shellSort(int[] a) {
int temp;
int d = a.length;
for (; ; ) {
d = d / 2;
//根据差值分组为子序列
for (int k = 0; k < d; k++) {
//此时对每组数列进行插入排序,数组为a[k+d],a[k+2d]...a[k+n*d]
for (int i = k + d; i < a.length; i += d) {
// a[j]是要插入的数字,从a[j]往a[0]比较,跨度为d
for (int j = i; j > k; j -= d) {
//如果插入的数小,交换位置
if (a[j] < a[j - d]) {
temp = a[j];
a[j] = a[j - d];
a[j - d] = temp;
} else {
//因为默认a[0]~a[i]是排好的,a[i+1]比a[i]大的话,就不用比较后面了
break;
}
}
}
}
if (d == 1) {
break;
}
}
}
快速排序 O(N*logN)
先从数列中取出一个数作为base值;
将比这个数小的数全部放在它的左边,大于或等于它的数全部放在它的右边;
对左右两个小数列重复第二步,直至各区间只有1个数。
public void quickSort(int a[], int l, int r) {
//左边必须大于右边
if (l >= r) {
return;
}
int i = l;
int j = r;
//选择第一个数为基准
int base = a[l];
while (i < j) {
//从右向左找第一个小于base的值,如果大于左移一位,直到找到小值或者i/j重合
while (i < j && a[j] > base) {
j--;
}
//从左向右找第一个大于base的值,如果小于右移一位,直到找到大值或者i/j重合
while (i < j && a[i] < base) {
i++;
}
//交换
if (i < j) {
int temp = a[j];
a[j] = a[i];
a[i] = temp;
}
}
//将基准值放到i右移到的位置
a[i] = base;
//将i左边和i右边分别排序
quickSort(a, l, i - 1);//递归调用
quickSort(a, i + 1, r);//递归调用
}
归并排序 O(N*logN)
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法的一个非常典型的应用。
首先考虑下如何将2个有序数列合并。
这个非常简单,只要从比较2个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数。
然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可。
private static void mergeSort(int[] a, int first, int last, int temp[]) {
if (first < last) {
//中间值
int middle = (first + last) / 2;
//左半部分排序
mergeSort(a, first, middle, temp);
//右半部分排序
mergeSort(a, middle + 1, last, temp);
//合并左右部分
mergeArray(a, first, middle, last, temp);
}
}
private static void mergeArray(int a[], int first, int middle, int end, int temp[]) {
int i = first;
int m = middle;
int j = middle + 1;
int n = end;
int k = 0;
while (i <= m && j <= n) {
if (a[i] <= a[j]) {
temp[k] = a[i];
k++;
i++;
} else {
temp[k] = a[j];
k++;
j++;
}
}
while (i <= m) {
temp[k] = a[i];
k++;
i++;
}
while (j <= n) {
temp[k] = a[j];
k++;
j++;
}
for (int r = 0; r < k; r++) {
a[first + r] = temp[r];
}
}
堆排序 O(N*logN)
利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
public static void heapSort(int a[]) {
//堆顶最大值和数组最后(叶节点)交换 长度-1 次
for (int i = a.length - 1; i > 0; i--) {
//构建大顶堆(最大堆)
buildHeap(a, i);
//堆顶最大值和数组最后(叶节点)交换
swap(a, 0, i);
}
}
//构建大顶堆(最大堆)
public static void buildHeap(int a[], int lastIndex) {
//排最后的非叶节点为 长度/2-1,从第i检查到堆顶第0项,上浮大值
for (int i = (lastIndex + 1) / 2 - 1; i >= 0; i--) {
//必定存在的左叶节点,不一定存在的右叶节点
int left = i * 2 + 1;
int right = i * 2 + 2;
//max为左右叶节点中的最大值
int max = left;
if (right <= lastIndex) {
if (a[left] < a[right]) {
max = right;
}
}
//上浮大值
if (a[i] < a[max]) {
swap(a, i, max);
}
}
}
//交换值
public static void swap(int a[], int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
基数排序 O(d(n+r))
【d代表关键字有d位,n代表n个记录,r代表r个空队列】
基数排序(radix sort),相对于常见的比较排序,基数排序是一种分配式排序,即通过将所有数字分配到应在的位置最后再覆盖到原数组完成排序的过程。
public static void radixSort(int[] a) {
//位数
int digit = 1;
//作为排序后数组的新下标
int newIndex = 0;
//供基数排序使用的二维数组,第一维度固定10位0~9,第二维度根据下标依次存放每次基数排序的结果
int[][] container = new int[10][a.length];
//第一维度每个数组的内容计数,最少为10,防止数组全是个位数时越界,例如五位数组最大值为8,counter.length=5 ,counter[8]就越界
int counterLength = 10;
if (a.length > 10) {
counterLength = a.length;
}
int[] counter = new int[counterLength];
//算出数组中最大的值,用来确定最大位
int max = a[0];
int maxDigit = 0;
for (int i = 0; i < a.length; i++) {
if (a[i] > max) {
max = a[i];
}
}
while (max > 0) {
max /= 10;
maxDigit++;
}
//对每位进行排序
while (digit <= maxDigit) {
//对每个数值该位取余,container[remainder],并计数该位置上数值的下标counter[remainder]
for (int num : a) {
int remainder = (num / digit) % 10;
container[remainder][counter[remainder]] = num;
counter[remainder]++;
}
//将上一步放入容器的数值依次覆盖到远数组中
for (int i = 0; i < 10; i++) {
for (int j = 0; j < counter[i]; j++) {
a[newIndex] = container[i][j];
newIndex++;
}
counter[i] = 0;
}
digit *= 10;
newIndex = 0;
}
}
8种排序算法 Java实现的更多相关文章
- 八种排序算法--java实现(转)
(转:http://blog.csdn.net/without0815/article/details/7697916) 8种排序之间的关系: 1, 直接插入排序 (1)基本思想:在要排序的一组数中, ...
- 学习Java绝对要懂的,Java编程中最常用的几种排序算法!
今天给大家分享一下Java中几种常见的排序算法的Java代码 推荐一下我的Java学习羊君前616,中959,最后444.把数字串联起来! ,群里有免费的学习视频和项目给大家练手.大神有空时也 ...
- java算法03 - 常用的8种排序算法
Java常用的八种排序算法: 插入排序 - 直接插入排序 每次将待排序的记录按照关键字的大小,插入到前面已经排好序的记录的适当位置.直到全部记录插入完成. 代码实现 /** * 直接插入排序 O(n^ ...
- 几种排序算法及Java实现排序的几种方式
几种排序算法 下面的例子介绍了4种排序方法: 冒泡排序, 选择排序, 插入排序, 快速排序 package date201709.date20170915; public class SortUtil ...
- Java 的八种排序算法
Java 的八种排序算法 这个世界,需要遗忘的太多. 背景:工作三年,算法一问三不知. 一.八种排序算法 直接插入排序.希尔排序.简单选择排序.堆排序.冒泡排序.快速排序.归并排序和基数排序. 二.算 ...
- 八大排序算法Java
目录(?)[-] 概述 插入排序直接插入排序Straight Insertion Sort 插入排序希尔排序Shells Sort 选择排序简单选择排序Simple Selection Sort 选择 ...
- 八大排序算法Java实现
本文对常见的排序算法进行了总结. 常见排序算法如下: 直接插入排序 希尔排序 简单选择排序 堆排序 冒泡排序 快速排序 归并排序 基数排序 它们都属于内部排序,也就是只考虑数据量较小仅需要使用内存的排 ...
- 几种排序算法的学习,利用Python和C实现
之前学过的都忘了,也没好好做过总结,现在总结一下. 时间复杂度和空间复杂度的概念: 1.空间复杂度:是程序运行所以需要的额外消耗存储空间,一般的递归算法就要有o(n)的空间复杂度了,简单说就是递归集算 ...
- 秒杀9种排序算法(JavaScript版)
一:你必须知道的 1> JS原型 2> 排序中的有序区和无序区 3> 二叉树的基本知识 如果你不知道上面三个东西,还是去复习一下吧,否则,看下面的东西有点吃力. 二:封装丑陋的原型方 ...
随机推荐
- h5+ 开发分享功能
h5+ 开发微信.QQ分享功能 此处只做微信网页分享示例代码 方式一.JS+HTML+h5Plus 1.html代码 <div class="button" onclick= ...
- Create First Application
Node.js创建第一个应用 Node.js开发的目的就是为了用JavaScript编写Web服务器程序, 在使用Node.js时,不仅仅是在实现一个应用,同时还实现了整个HTTP服务器.在创建Nod ...
- Python3高级核心技术97讲
可以毫不夸张的说:这门课程是初中级Python开发人员向高级进阶的必学课程 许多Pythoner喜欢追求新的框架,但却不重视Python本身基础知识的学习, 他们不知道的是,语言本身的进阶优先于框架, ...
- linux添加策略路由python脚本(待完善)
#! _*_ coding:utf-8 _*_ import os,sys,re,fileinput,socket device_list = [] ip_list = [] ip_end = [] ...
- 线程的同步机制:同步代码块&同步方法
解决存在的线程安全问题:打印车票时出现重票,错票 使用同步代码块的解决方案 TestWindow2 package com.aff.thread; /* 使用实现Runnable接口的方式,售票 存在 ...
- & vue项目中的rem适配
有个朋友问我在vue项目怎么做rem适配,我工作中都是用的dva,但是我感觉道理都是一样的,换汤不换药.配完就顺手写下来吧! 需要安装两个插件库 lib-flexible和px2rem-loader ...
- PMP | 备考笔记
(持续更新......) 五大过程组和十大知识领域是PMP的重要组成部分,也是这门课的重点线索,本文会逐步迭代.渐进明细的来补充完善这个体系. (先放个图吧) 以下每个模块记录自己有点模糊的地方 项目 ...
- parrot os 创建swap分区&swapon failed invalid argument解决
parrot os(不仅仅是debian系统),分区提示,查看系统格式为btrfs,需要注意的是btrfs无法添加swap分区,但是可以在5.0内核以上添加 以下命令,完成创建8g的swap分区 to ...
- 02 . Tomcat多实例并用Nginx反代
Tomcat虚拟主机 一个应用程序在某一个端口启动运行产生了一系列的进程就是一个实例,让tomcat启动两个不同的相互独立的进程,产生两个不同的套接字,分别运行在不同的端口,让不同的端口响应不同的 ...
- No grammar constraints (DTD or XML Schema) referenced in the document.的两种解决办法
方法一:常用方法 关闭XML验证 工具栏:windows => preferences => xml => xml files => validation => Indi ...