java快速排序直观演示代码,排序算法总结(含动图演示和Java代码实现)

本文将围绕冒泡排序、桶排序、计数排序、堆排序、插入排序、并归排序、快速排序和选择排序,按照描述、时间复杂度(最坏情况)、动态图展示和代码实现来讲解。本文默认排序为从小到大。

本文相关代码已上传至github,欢迎关注https://github.com/zhuzhenke/common-algorithms

公用方法

SortUtils

public class SortUtils {

public static void check(int[] sortingData) {

if (sortingData == null || sortingData.length == 0) {

throw new IllegalArgumentException("sortingData can not be empty!");

}

}

public static void swap(int[] swapArray, int i, int j) {

check(swapArray);

if (i < 0 || i > swapArray.length - 1) {

throw new ArrayIndexOutOfBoundsException("illegal index i:" + i);

}

if (j < 0 || j > swapArray.length - 1) {

throw new ArrayIndexOutOfBoundsException("illegal index j:" + j);

}

int temp = swapArray[i];

swapArray[i] = swapArray[j];

swapArray[j] = temp;

}

public static int getMaxValue(int[] sortingData) {

check(sortingData);

int max = sortingData[0];

for (int value : sortingData) {

if (value < 0) {

throw new IllegalArgumentException("value could not be negative:" + value);

}

if (value > max) {

max = value;

}

}

return max;

}

}

冒泡排序

描述

比较前后两个数的大小,如果前者大于后者,则交换两个数的位置

最大的数字在进行一轮比较和交换后,会出现在数组的最后一个位置

每一轮之后,可减少最大数字的比较。重复上述操作直到没有需要比较的元素为止

时间复杂度

O(n^2)

动态图展示

Bubble-sort-example-300px.gif

代码实现

github代码

public int[] sort(int[] sortingData) {

SortUtils.check(sortingData);

for (int j = sortingData.length - 1; j > 0; j--) {

for (int i = 0; i < j; i++) {

if (sortingData[i] > sortingData[i + 1]) {

SortUtils.swap(sortingData, i, i + 1);

}

}

}

return sortingData;

}

桶排序

描述

挑选数组中最大的数字,设置默认分配的桶数,得到每个桶容纳的数字范围。如最大是10,桶是4个,则每个桶最大容纳3个数字。第0个桶放0、1、2、3,第1个桶方4、5、6,第2桶方7,8,9,以此类推

对每个桶内进行冒泡排序或选择排序

遍历所有桶,依次取出每个桶中的元素,得到的就是一个排好序的数组

时间复杂度

O(n^2)

动态图展示

87c55f2366dbad9e8b0cbb4f1dc3e4ba.png

87c55f2366dbad9e8b0cbb4f1dc3e4ba.png

代码实现

github代码

@Override

public int[] sort(int[] sortingData) {

SortUtils.check(sortingData);

int bucketSize = (int) Math.round(Math.sqrt(sortingData.length)) + 1;

int[][] buckets = new int[bucketSize][];

int max = SortUtils.getMaxValue(sortingData);

double avgContain = Math.ceil((double) max / (double) bucketSize);

for (int value : sortingData) {

int bucketIndex = (int) Math.ceil(value / avgContain) - 1;

if (bucketIndex < 0) {

bucketIndex = 0;

}

int[] bucketIndexs = buckets[bucketIndex];

if (bucketIndexs == null || bucketIndexs.length == 0) {

bucketIndexs = new int[1];

bucketIndexs[0] = value;

buckets[bucketIndex] = bucketIndexs;

} else {

int[] newBucketIndexs = new int[bucketIndexs.length + 1];

System.arraycopy(bucketIndexs, 0, newBucketIndexs, 0, bucketIndexs.length);

newBucketIndexs[bucketIndexs.length] = value;

buckets[bucketIndex] = newBucketIndexs;

}

}

Sort sort = new InsertionSort();

for (int a = 0; a < buckets.length; a++) {

int[] bucket = buckets[a];

if (bucket == null || bucket.length == 0) {

continue;

}

bucket = sort.sort(bucket);

buckets[a] = bucket;

}

int[] result = new int[sortingData.length];

int resultIndex = 0;

for (int[] bucket : buckets) {

if (bucket == null || bucket.length == 0) {

continue;

}

for (int bucketValue : bucket) {

result[resultIndex++] = bucketValue;

}

}

return result;

}

计数排序

描述

获取数组中最大的值(这个值需要在可控范围,最好是在10000以内)

创建一个长度为最大值加1的计数数组,

遍历待排序数组,将元素的值落入到计数数组的下标元素,将下标元素的值加1

遍历下标数组,将后一个元素的值标为当前元素值加前一个元素的值(用于排序后的数组下标)。

创建一个长度跟待排序数组大小相同的结果数组

遍历待排序数组,取出待排序元素,对应计数数组的下标元素,并放在计数元素值的前一个位置,并将计数元素值减1

时间复杂度

O(n)

动态图展示

f86f9118ae5e642899c8e4217fded61c.png

代码实现

github代码

private int[] sort2(int[] sortingData) {

int maxValue = SortUtils.getMaxValue(sortingData);

//get max,check all numbers must be bigger or equal 0

int[] count = new int[maxValue + 1];

//count every number

for (int value : sortingData) {

count[value] = count[value] + 1;

}

for (int i = 1; i < count.length; i++) {

count[i] = count[i] + count[i - 1];

}

//output

int[] result = new int[sortingData.length];

for (int value : sortingData) {

result[count[value] - 1] = value;

count[value] = count[value] - 1;

}

return result;

}

堆排序

描述

为了方便理解,将数组元素映射成二叉树,array[0]对一个根节点,array[1]为根的左节点,array[2]为根的右节点,一次类推

从最后一个元素开始遍历到第一个,让其与父节点比较大小,如果子节点大,则交换位置。(另外一种方式是从中间元素开始比较,得到当前元素和子元素的最大值,这样则遍历深度为logn,这种方式属于推荐方式)

遍历一轮结束后,则最大值已经位于index为0的位置,这时交换index为0和最后一位的位置,则最大值确定。下一轮比较从最大值的前一个index下标元素开始遍历,依次进行遍历

最后全部遍历完成,则得到一个拍好序的数组

时间复杂度

O(nlogn)

动态图展示

Sorting_heapsort_anim.gif

代码实现

github代码

public int[] sort(int[] sortingData) {

int highIndex = sortingData.length - 1;

while (highIndex > 0) {

for (int i = 1; i <= highIndex; i++) {

sortBiggestToIndex0(sortingData, i);

}

SortUtils.swap(sortingData, 0, highIndex);

highIndex--;

}

return sortingData;

}

public static void sortBiggestToIndex0(int[] sortingData, int sortIndex) {

while (sortIndex > 0 && sortingData[sortIndex] > sortingData[(sortIndex - 1) / 2]) {

SortUtils.swap(sortingData, sortIndex, (sortIndex - 1) / 2);

sortIndex = (sortIndex - 1) / 2;

}

}

插入排序

描述

插入排序类似于扑克摸牌排序

第一次只有一种牌,牌是有序的。当摸到第二张牌时,则插入到已有的排好序的牌中,此时前两张牌有序

依次进行同样的操作,摸到第n张牌时,前n-1张牌已经有序,进行插入到合适位置即可

时间复杂度

O(n^2)

动态图展示

9400029b6559a5f16c48610324ceb961.png

代码实现

github代码

public int[] sort(int[] sortingData) {

SortUtils.check(sortingData);

for (int i = 1; i < sortingData.length; i++) {

int currentValue = sortingData[i];

int j = i;

while (j - 1 >= 0 && currentValue < sortingData[j - 1]) {

sortingData[j] = sortingData[j - 1];

j--;

}

sortingData[j] = currentValue;

}

return sortingData;

}

并归排序

描述

并归排序利用递归思想,递归思想的核心在于找到一个模式,分解为子模式,子模式又可以分解子模式,则对于最小子模式,可以直接求解。

首先会将待排序数组分为两份,两份分别排好序后进行合并

两份中的每一份,又可以查分为更小的一份,直到每份只有一个元素,则此份为已排好序的子数组。对两个子数组进行合并的排序

时间复杂度

O(nlogn)

动态图展示

472002c594283faeb1ddac89e7edfc2c.png

代码实现

github代码

@Override

public int[] sort(int[] sortingData) {

SortUtils.check(sortingData);

splitDate(sortingData, 0, sortingData.length - 1);

return sortingData;

}

private void splitDate(int[] sortingData, int start, int end) {

if (end - start < 1) {

return;

}

int middle = (start + end) / 2;

splitDate(sortingData, start, middle);

splitDate(sortingData, middle + 1, end);

mergeData(sortingData, start, middle, end);

}

private void mergeData(int[] sortingData, int start, int middle, int end) {

int[] left = Arrays.copyOfRange(sortingData, start, middle + 1);

int[] right = Arrays.copyOfRange(sortingData, middle + 1, end + 1);

int i = 0;

int j = 0;

for (int k = start; k <= end; k++) {

if (i < left.length && j < right.length) {

if (left[i] <= right[j]) {

sortingData[k] = left[i];

i++;

} else {

sortingData[k] = right[j];

j++;

}

} else {

if (i >= left.length) {

sortingData[k] = right[j];

j++;

} else if (j >= right.length) {

sortingData[k] = left[i];

i++;

}

}

}

}

快速排序

描述

选择待排序数组的中元元素,一般选择第一个或最后一个元素,将数组拆分为两部分,左边部分元素小于等于中元元素,右边部分元素大于中元元素

继续将子数组按中元元素进行拆分,直到全部排好序位置

时间复杂度

O(n^2)

动态图展示

cb345b3b3dc2ae27314570d8aa9b1830.png

代码实现

github代码

@Override

public int[] sort(int[] sortingData) {

SortUtils.check(sortingData);

quickSort(sortingData, 0, sortingData.length - 1);

return sortingData;

}

private void quickSort(int[] sortingData, int start, int end) {

if (start > end) {

return;

}

int middle = getQuickSortMiddle(sortingData, start, end);

quickSort(sortingData, start, middle - 1);

quickSort(sortingData, middle + 1, end);

}

/**

* one side

*/

public int getQuickSortMiddle(int[] sortingData, int start, int end) {

int i = start;

int pivot = end;

for (int j = start; j < end; j++) {

if (sortingData[j] < sortingData[pivot]) {

SortUtils.swap(sortingData, i, j);

i++;

}

}

SortUtils.swap(sortingData, i, pivot);

return i;

}

选择排序

描述

从第一个元素开始遍历,记录最小值和对应元素下标,遍历一轮则可以得到最小值,将这个值与下标为0的元素交换,则完成第一轮最小值输出

从第2个进行同样的遍历操作,遍历取剩余元素的最小值,将这个值与下标为1的元素交换

从第index个开始进行遍历操作,遍历取剩余元素的最小值,将这个值与下标为index的元素交换

遍历直到最后一个元素位置,得到一个排好序的数组

时间复杂度

O(n^2)

动态图展示

Selection-Sort-Animation.gif

代码实现

github代码

public int[] sort(int[] sortingData) {

SortUtils.check(sortingData);

for (int index = 0; index < sortingData.length; index++) {

int smallestIndex = index;

int smallestValue = sortingData[index];

for (int j = index; j < sortingData.length; j++) {

if (sortingData[j] < smallestValue) {

smallestValue = sortingData[j];

smallestIndex = j;

}

}

sortingData[smallestIndex] = sortingData[index];

sortingData[index] = smallestValue;

}

return sortingData;

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/427039.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

scrapy ip地址 tcp time out_TCP的运作流程(一)——“三次握手”

前言看过前面有关两篇HTTP的文章的同学&#xff0c;想必对HTTP已经有了一定的了解。在HTTP初始(一)中提到过TCP/IP四层网络模型&#xff0c;这次我们就来详细了解一下TCP传输。因为时间和篇幅所限&#xff0c;本篇讲分为两章&#xff0c;本章讲TCP的三次握手&#xff0c;下章讲…

c++,c.c#区别

C则一般看作是对C语言的扩展。 Java语言是一种完全的面向对象语言&#xff0c;虽然它的底层&#xff08;运行时库&#xff09;是用C语言开发的&#xff0c;可是并不依赖于C。 C#是微软开发的一种编程语言&#xff0c;语法类似Java&#xff0c;几乎就是从Java的翻版。 &#xff…

php.ini 老薛,出现Allowed memory size of 134217728 bytes exhausted怎么办?

有站长在交流群内说到使用 ZBlogPHP 建站在发布文章的时候总是出现以下错误&#xff1a;Allowed memory size of 134217728 bytes exhausted(tried to allocate 12288 bytes)允许耗尽内存大小为 134217728 字节(试图分配 12288 字节)具体如下图所示&#xff1a;134217728 bytes…

winform窗体

WinForm是Net开发平台中对Windows Form的一种称谓。 中文名 Winform 特 点 功能强大 操作方便 新的数据提供程序管理 使用安全 利用公共语言运行库的安全特性 特点 Windows窗体的一些重要特点如下&#xff1a; 功能强大 Windows窗体可用于设计窗体和可视控件&#xff0c;以创建…

实例3:python

#一个整数&#xff0c;它加上100后是一个完全平方数&#xff0c;再加上168又是一个完全平方数&#xff0c;请问该数是多少&#xff1f; #假设该数为 x。 #1、则&#xff1a;x 100 n2, x 100 168 m2 #2、计算等式&#xff1a;m2 - n2 (m n)(m - n) 168 #3、设置&…

实例4:python

#输入某年某月某日&#xff0c;判断这一天是这一年的第几天&#xff1f; #!/usr/bin/python -- coding: UTF-8 -- #!/usr/bin/python -- coding: UTF-8 -- yearint(2019) monthint(8) dayint(13) months1[0,31,60,91,121,152,182,213,244,274,305,335,366] #闰年 months2[…

php html登陆逻辑,保持演示文稿(HTML)和逻辑(PHP)分开

我试图保持演示和逻辑分离,而不使用像Smarty这样的模板引擎.到目前为止我所做的工作是有效的,但我不知道如果不在我的演示文稿中添加更多PHP而不是我想做的事情.例如,现在我有这样的事情&#xff1a;product_list.phptry {$query $conn->prepare("SELECT p.id,p.name,…

层次分析法matlab_建模开讲课程回放2:层次分析法及其MATLAB

建模开讲&#xff1a;层次分析法及其MATLAB实践主讲人&#xff1a;于晶贤老师课程回放地址如下&#xff0c;大家可以复制链接到地址栏即可观看&#xff0c;也可以直接点击左下角的观看&#xff1a;https://ke.qq.com/webcourse/index.html?fromqqchat&cid493154&term_…

raw input()和input区别

版本差异 raw_input——》python2版本 input——》python3版本 2. 输入格式差异 就是raw_input()随便输都是字符串&#xff0c;而input()必须按照Python的规则来~ raw_input() nameraw_input(‘输入姓名&#xff1a;’) ageraw_input(‘输入年龄’) 我们输入汉字的姓名和数…

不同vlan之间如何ping通_【丰润达.安防百科】如何实现交换机不同VLAN、不同网段之间互访?...

交换机如何实现不同网段的互访&#xff1f;这个交换机完全可以实现&#xff0c;在实际项目中&#xff0c;交换机实现不同网段的互访用的也比较多&#xff0c;那么今天我们一起来看下。▎同一个vlan中&#xff0c;不同网段的主机如何互通同一个vlan&#xff0c;不同网段的主机如…

实例5:python

#输入三个整数x,y,z&#xff0c;请把这三个数由小到大输出。 l [] for i in range(3): x int(input(‘integer:\n’)) l.append(x) l.sort() print (l)

背景图层和普通图层的区别_008Photoshop四赞图层(图层样式)

图层过滤器图层滤镜&#xff0c;比如你只想看到像素图层&#xff0c;选择像素图层过滤器&#xff0c;这时就只能看到背景图层了(在图层面板)&#xff0c;如果再点击像素图层过滤器&#xff0c;其他图层又出现了。选中调整图层过滤器&#xff0c;就只能看到图层结构里的调整图层…

实例6:python

#斐波那契数列&#xff08;Fibonacci sequence&#xff09;&#xff0c;又称黄金分割数列&#xff0c;指的是这样一个数列&#xff1a;0、1、1、2、3、5、8、13、21、34、……。 #F0 0 (n0) #F1 1 (n1) #Fn F[n-1] Fn-2 #!/usr/bin/python -- coding: UTF-8 -- #def fib(…

vue devtools面板没有显示_vue 基础入门(四)

vue 基础入门(四)1.全局配置Vue.config 是一个对象&#xff0c;包含 Vue 的全局配置。可以在启动应用之前修改下列 property&#xff1a;1.1 silent类型&#xff1a;boolean默认值&#xff1a;false用法&#xff1a;Vue.config.silent true❝取消 Vue 所有的日志与警告。❞1.2…

vue 生命周期_Vue生命周期小白看了都会的

最近一直在学习Vue&#xff0c;而vue生命周期是我们不可能绕开的一个很核心的知识点&#xff0c;今天来简单的梳理一下大概的内容。一、钩子函数在一开始学习的时候&#xff0c;总有钩子函数这个名词冒出来&#xff0c;而且在vue官网文档中也频繁出现&#xff0c;也相信给很多初…

实例7:python

#将一个列表的数据复制到另一个列表中。 #程序分析&#xff1a;使用列表[:]。 #程序源代码&#xff1a; #!/usr/bin/python -- coding: UTF-8 -- #a [1, 2, 3] #b a[:] #print (b) #import copy #a [1, 2, 3] #bcopy.copy(a) #print(b) #[1, 2, 3] #使用 Python3 的参…

实例8:python

#输出 9*9 乘法口诀表。 #!/usr/bin/python -- coding: UTF-8 -- #for i in range(1, 10): print for j in range(1, i1): print ("%d*%d%d" % (i, j, i*j),) #!/usr/bin/python3 i0 j0 while i<9: i1 while j<9: j1 print(j,“x”,i,"",i*j,…

ant man 什么意思_浅谈为什么很多蓝牙模块厂家选择nRF52832?

浅谈为什么很多蓝牙模块厂家选择nRF52832&#xff1f;现在蓝牙低功耗(BLE)SOC作为新一代蓝牙&#xff0c;以其低功耗的优势&#xff0c;正凸显出强大的市场竞争力&#xff0c;而其中Nordic公司的nRF52832这一款低功耗蓝牙芯片更是受到大家的欢迎。Nordic是一家无晶圆厂半导体公…

实例9:python

#题目&#xff1a;暂停一秒输出。 #程序分析&#xff1a;使用 time 模块的 sleep() 函数 #!/usr/bin/python -- coding: UTF-8 -- import time l[1,2,3,4] for i in range(len(l)): print (l[i]) time.sleep(5) # 暂停一秒输出

php对话框制作,织梦系统“提示窗口对话框类”详解,oxwindow.class.php、catalog_do.php...

如果对织梦系统做过二次开发或学深入研究过的话&#xff0c;一定会知道在我们做织梦二次开发时&#xff0c;一般会把php文件以及对应的模板文件起的名字&#xff0c;除了扩展名外&#xff0c;其它都一样&#xff0c;这是织梦文件起名的一个特点。例如&#xff0c;index_body.ph…