Java基础复习笔记基本排序算法

1. 排序

排序是一个历来都是很多算法家热衷的领域,到现在还有很多数学家兼计算机专家还在研究。而排序是计算机程序开发中常用的一种操作。为何需要排序呢。我们在所有的系统中几乎都要检索数据,而这些欲检索的数据如果有规律的话,比如按照某些字段、属性降序排序的话,那么从这些有规律的数据查询结果或者结果集的话就快速得多。

2. 常用算法

常用的算法有:直接选择排序、堆排序、冒泡排序、快速交换排序、直接插入排序、折半插入排序、Shell排序、归并排序、桶式排序、基数排序。这些都属于常用排序算法,也都是内部排序算法。所谓内部排序就是不借助任何外部的内存处理器,直接使用内存,在内存中完成就可以的排序方式。

3. 直接选择排序

直接排序的思想就是进行二重遍历,由外层元素依次和内层元素进行对比,之后交换位置。算法如下

package sort;
import java.util.Arrays;
/**
* 选择排序
*/
public class SelectSort {
// 选择排序法
public static void selectSort(Integer[] integers) {
for (int i = 0; i < integers.length - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < integers.length; j++) {
if (integers[i] < integers[j]
&& integers[minIndex] < integers[j]) {
// 只记住标记
minIndex = j;
}
}
// 每次只交换一次即可
if (minIndex != i) {
Integer temp = integers[i];
integers[i] = integers[minIndex];
integers[minIndex] = temp;
}
}
}
}

4. 堆排序

堆排序的思想就是将要排序的数组看成一个完全二叉树(出最后一层节点外,其他节点都是2个子节点),之后建立大顶堆,将完全二叉树建立成一个父节点值都大于它的子节点的树。之后将根节点和要排序的数组的最后一个元素进行换位。之后除了数组最后一个元素外重复建堆过程。算法如下

package sort;
import java.util.Arrays;
/**
* 堆排序
*/
public class HeapSort {
/**
* 构建堆数组
*/
public static void buildHeap(Integer[] datas, int lastIndex) {
//从目标的父节点开始遍历
for (int i = (lastIndex - 1) / 2; i >= 0; i--) {
//记录父节点位置
int maxIndex = i; //当父节点的子节点存在的时候
while (maxIndex * 2 + 1 <= lastIndex) { //默认附一个大值为父节点的左子节点的索引
int biggerIndex = maxIndex * 2 + 1; //此处判断是否父节点还有一个右子节点
if (biggerIndex < lastIndex) {
//如果有右子节点判断左右子节点的值大小,记录一个最大的位置,好用于交换
if (datas[biggerIndex] < datas[biggerIndex + 1]) {
biggerIndex++;
}
} //此处是比较父节点值和左右子节点值,找个最大的做父亲
if (datas[maxIndex] < datas[biggerIndex]) {
Integer temp = datas[maxIndex];
datas[maxIndex] = datas[biggerIndex];
datas[biggerIndex] = temp; //记录一下最大值的索引
maxIndex = biggerIndex;
} else {
break;
}
}
}
}
/**
* 堆排序
*/
public static void heapSort(Integer[] datas) { // 数组大小
int arrayLength = datas.length; // 遍历数组
for (int i = 0; i < arrayLength - 1; i++) { // 构建堆
buildHeap(datas, arrayLength - 1 - i); // 交换元素
Integer temp = datas[0];
datas[0] = datas[arrayLength - 1 - i];
datas[arrayLength - 1 - i] = temp;
}
}

5. 冒泡排序

冒泡排序在使用频率上来说,也许是仅次于直接选择排序的算法的了。因为起泡的思想也很简单就是循环数组中的元素,相邻元素一一对比,进行交换。算法如下

package sort;
import java.util.Arrays;
/**
* 冒泡排序法
*/
public class BubbleSort {
/**
* 冒泡排序
*/
public static void bubbleSort(Integer[] datas) {
int datasLength = datas.length;
for (int i = 0; i < datasLength - 1; i++) {
for (int j = 0; j < datasLength - 1 - i; j++) {
if (datas[j] < datas[j + 1]) { // 交换之
Integer temp = datas[j + 1];
datas[j + 1] = datas[j];
datas[j] = temp;
}
}
}
}
}

6. 快速排序

所谓快速排序法是从待排序的数组中找一个标本作为分界值(一般是数组的第一个元素),所有比这个值小的值放到它的左边(或者右边),将比它大的值放到它的右边(或者左边),这样这个分界值左右两边的值要么全部比它大,要么全部比它小。之后再利用递归,将此标本右边、左边的所有元素也按部就班。算法如下

package sort;
import java.util.Arrays;
/**
* 快速排序
*/
public class QuickSort {
/**
* 交换数组元素位置
*/
public static void chang(Integer[] datas, int i, int j) {
Integer temp = datas[i];
datas[i] = datas[j];
datas[j] = temp;
}
/**
* 快速排序法
*/
public static void quickSort(Integer[] datas, int startIndex, int endIndex) { if (startIndex < endIndex) { //标本
Integer startData = datas[startIndex]; //左边的开始索引
int i = startIndex; //右边的开始索引
int j = endIndex + 1;
while (true) { //找左边比标本大的下标
while (i < endIndex && datas[++i] > startData){
} //找右边比标本小的下标
while (j > startIndex && datas[--j] < startData){
} if (i < j) {
//交换i、j元素位置
chang(datas, i, j);
} else {
break;
}
} //交换开始位置、j的元素为止
chang(datas, startIndex, j); //递归标本左边
quickSort(datas, startIndex, j - 1); //递归标本右边
quickSort(datas, j + 1, endIndex);
}
}
}

7. 直接插入排序

直接插入排序的原理就是将数组中的元素依次和前面元素进行比较,如果发现了比它大的(或者小的),记录标志位、记录被比较元素,之后从标志位一位一位的向后进行元素移动,之后空出来的的那一位就是留给被比较元素的。这样造成了一个现象就是被比较的元素前面的所有元素都是排序过了的。算法如下。

package sort;
import java.util.Arrays;
/**
* 直接插入排序
*/
public class InsertSort {
/**
* 直接插入
*/
public static void insertSort(Integer[] datas) { //从数组第二个元素开始遍历
for (int i = 1; i < datas.length; i++) { //当前元素和前一个元素进行对比【此处前面的元素已经排序好了】
if (datas[i] < datas[i - 1]) { //记录当前要比较的元素值
Integer temp = datas[i]; //从当前元素往前开始比较
int j = i - 1; //如果满足前面索引有效并且前面的元素值都是比当前值大的,那就进行元素后移动操作
for (; j >= 0 && datas[j] > temp; j--) { //元素后移
datas[j + 1] = datas[j]; } //前移操作后,j的索引就是中间那个比前面元素大,比后面元素小的位置索引-1
//将其要对比的值插进去
datas[j + 1] = temp;
}
}
}
}

8. 折半插入排序

折半插入排序是在原直接插入的基础上作了改进。对于折半插入法,被比较的元素不用和前面所有的元素进行一一对比,而是先找到0位元素到此被比较元素的中点元素,和这个重点元素进行比较,看看谁大,之后就是被比较元素元素和这个中点元素之间再找一个中点进行比较,或者是0点和原中点元素找个新中点。这样就可以缩小范围,反正排在被比较元素之前的元素是一个已经排好大小的序列,那就可以善加利用这已经排好的序列。当然了,找到位置后,该移动元素的还是要移动的。算法如下:

package sort;
import java.util.Arrays;
/**
* 折半排序
*/
public class BinaryInsertSort {
/**
* 折半排序
*/
public static void binaryInsertSort(Integer[] datas) { // 从数组第二个元素开始遍历
for (int i = 1; i < datas.length; i++) {
// 记录当前要比较的元素值
Integer temp = datas[i]; // 低位开始
int low = 0; // 高位开始
int hight = i - 1; // 位置有效,低位、高位
while (low <= hight) {
// 中间位置
int mind = (low + hight) / 2; //被比较元素大于中间元素
if (temp > datas[mind]) { //低位调整在中点之后
low = mind + 1;
} else {//被比较元素小于中间元素 //高位在中点之前
hight = mind - 1;
}
}
// 低高位调整完毕后,将中点元素依次往后移动
for (int j = i; j > low; j--) {
// 元素后移
datas[j] = datas[j - 1]; }
// 前移操作后,low的索引就是中间那个比前面元素大,比后面元素小的位置索引low
// 将其要对比的值插进去
datas[low] = temp;
}
}
}

9. 归并排序

归并排序的主要思想就是将原来的数组分开成2大部分,建立一个新的临时数组,分别从2部分开始顺序走,将2部分的元素进行比较,先将小元素放入到临时数组,之后索引往前走一位,剩下的在进行比较。算法如下:

package sort;
import java.util.Arrays;
/**
* 归并排序
*/
public class MergeSort {
/**
* 归并排序
*/
public static void mergeSort(Integer[] datas, int leftIndex, int rightIndex) { //当分块索引有效时
if (leftIndex < rightIndex) { //找出中间索引
int center = (leftIndex + rightIndex) / 2; //把左边到中点的元素集合继续分堆儿
mergeSort(datas, leftIndex, center); //把右边到中点的元素集合继续分堆儿
mergeSort(datas, center + 1, rightIndex); //归并
merge(datas, leftIndex, center, rightIndex);
}
}
/**
* 归并
*/
private static void merge(Integer[] datas, int left, int center, int right) { //建立一个临时的数组,用于装载排序后的数组
Integer[] temp = new Integer[datas.length]; //第二队的开始索引位置
int mind = center + 1; //临时数组从第一队的索引开始
int third = left; //仅仅记录开始索引位置
int tmp = left;
while (left <= center && mind <= right) {//分队后的数组进行比较
if (datas[left] <= datas[mind]) {
//左边的略小,左边索引前进
temp[third++] = datas[left++];
} else { //右边的略小,右边索引前进
temp[third++] = datas[mind++];
}
} //如果第二队数组还没走完,继续走完,将第二队右边的元素都放到临时数组后面
while (mind <= right) {
temp[third++] = datas[mind++];
} //如果第一队数组还没走完,继续走完,将第一队右边的元素都放到临时数组后面
while (left <= center) {
temp[third++] = datas[left++];
} //将临时数组中的所有元素(排序好的),原样覆盖到原先的数组
while (tmp <= right) {
datas[tmp] = temp[tmp++];
}
}
}

总结到这里发现自己实在不行了。要吐了,算法真的是数学大师+计算机专业的人才能搞得了得。相当于大脑就是一个编译器+数学公式器+内存监视器。向所有世界上还在为算法而奋斗的人们,先总结到这里。

Java基础复习笔记基本排序算法的更多相关文章

  1. Java基础复习笔记系列 四 数组

    Java基础复习笔记系列之 数组 1.数组初步介绍? Java中的数组是引用类型,不可以直接分配在栈上.不同于C(在Java中,除了基础数据类型外,所有的类型都是引用类型.) Java中的数组在申明时 ...

  2. Java基础复习笔记系列 九 网络编程

    Java基础复习笔记系列之 网络编程 学习资料参考: 1.http://www.icoolxue.com/ 2. 1.网络编程的基础概念. TCP/IP协议:Socket编程:IP地址. 中国和美国之 ...

  3. Java基础复习笔记系列 八 多线程编程

    Java基础复习笔记系列之 多线程编程 参考地址: http://blog.csdn.net/xuweilinjijis/article/details/8878649 今天的故事,让我们从上面这个图 ...

  4. Java基础复习笔记系列 七 IO操作

    Java基础复习笔记系列之 IO操作 我们说的出入,都是站在程序的角度来说的.FileInputStream是读入数据.?????? 1.流是什么东西? 这章的理解的关键是:形象思维.一个管道插入了一 ...

  5. Java基础复习笔记系列 五 常用类

    Java基础复习笔记系列之 常用类 1.String类介绍. 首先看类所属的包:java.lang.String类. 再看它的构造方法: 2. String s1 = “hello”: String ...

  6. Java基础复习笔记系列 三

    前几节都是基础中的基础,从第三讲的笔记开始,每次笔记针对Java的一个知识块儿.  Java异常处理 1.什么是异常? 异常是指运行期出的错误.比如说:除以一个0:数组越界:读取的文件不存在. 异常处 ...

  7. Java基础复习笔记系列 二

    1.Java中Static的相关用法总结?(静态方法:静态变量:静态代码块) public static void main(String args[])执行的关键,在于有static.有了stati ...

  8. Java基础复习笔记系列 十三 反射机制

    主题:Java反射机制 学习资料参考网址: 1.http://www.icoolxue.com 1.Java反射机制. 各种框架中都使用到了Java的反射机制. 两个类:java.lang.Class ...

  9. 尚学堂JAVA基础学习笔记

    目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...

随机推荐

  1. emSecure Use Digital Signatures to protect your products

    emSecure Use Digital Signatures to protect your products emSecure is an RSA based software solution ...

  2. How to change the implementation (detour) of an externally declared function

    原文地址:http://stackoverflow.com/questions/6905287/how-to-change-the-implementation-detour-of-an-extern ...

  3. Apache CXF JAX-WS example

    1. 环境说明 jdk 1.6.0_29 apache cxf  2.7.7 2. 新建JavaProject 3. 添加jar包,将apache cxf下面lib里面的jar包都添加到项目中(可能有 ...

  4. 从UEditor内容中获取指定节点值(转)

    今天吐槽一下百度的富文本编辑器UEditor,这种富文本编辑器极大地方便我们上传文件,开发人员无需编写任何上传代码,只需配置几个路径即可.但高度集成的东西有时也显得笨重,灵活度不高.比如:编辑器中我既 ...

  5. Html5游戏框架createJS组件--EaselJS

    CreateJS库是一款HTML5游戏开发的引擎,是一套可以构建丰富交互体验的HTML5游戏的开源工具包,旨在降低HTML5项目的开发难度和成本,让开发者以熟悉的方式打造更具现代感的网络交互体验. 掌 ...

  6. Spark LDA实战

    选取了10个文档,其中4个来自于一篇论文,3篇来自于一篇新闻,3篇来自于另一篇新闻. 首先在pom文件中加入mysql-connector-java: <dependency> <g ...

  7. 动态库DLL中类的使用

    一.DLL中类的导出 在类名称前添加 _declspec(dllexport)定义,比如: class _declspec(dllexport) CMath{ .... }; 通常使用预编译开关切换类 ...

  8. 创建一个可拖动的DIV

    var drag = function(){ var obj = document.getElementById("id"); var s = obj.style; var b = ...

  9. 12C -- DDL日志

    DDL日志和alert日志有相似的格式和行为.但是只包含DDL语句日志.oracle只是为数据库组件提供DDL日志,且需要将参数enable_ddl_logging设置为true. 在DDL日志中,每 ...

  10. Oracle之外键(Foreign Key)使用方法具体解释(二)- 级联删除(DELETE CASCADE)

    Oracle外键(Foreign Key)之级联删除(DELETE CASCADE) 目标 演示样例解说怎样在Oracle外键中使用级联删除 什么是级联删除(DELETE CASCADE)? 级联删除 ...