Java实现数据结构中的八种排序方法,java面试手写代码

/**

  • 直接插入排序

  • @param data

  • @return

*/

public void insertSort(int[] data){

int i, j, tmp;

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

if(data[i]<data[i-1]){

tmp = data[i];//需要交换数据,先保存待插入的数字

for(j=i-1;j>=0&&data[j]>tmp;j–){

data[j+1] = data[j];//比较大的都往后挪一位

}

data[j+1] = tmp;//因为i之前的已经有序,只要有一个小于等于data[i]的数字,这个数字后一位就是插入的位置

}

}

System.out.println(Arrays.toString(data));

}

2、冒泡排序


n个元素进行冒泡排序时,首先将第一个元素和第二个元素进行比较,若为逆序则交换二者位置,此时较大的元素被放到了后面,接着用二者中较大的第二个元素和第三个元素进行比较,依次类推,直到第n-1个元素和第n个元素比较完成后,完成一趟冒泡排序,最大的元素被交换到第n位。

冒泡排序

然后对前n-1个元素进行一趟冒泡,结果是第二大的元素交换到第n-1的位置。

完成最多n-1趟冒泡后,所有元素有序排列。某趟冒泡过程中没有进行任何元素交换,则可以结束排序过程。

/**

  • 冒泡排序

  • @param data

  • @return

*/

public void bubbleSort(int[] data){

int i, j;

for(i=0;i<data.length-1;i++){

boolean flag = true;//用于判断本次冒泡是否进行了交换

for(j=0;j<data.length-i-1;j++){//第i次排序时最后i个元素已经有序

if(data[j]>data[j+1]){

swap(data, j, j+1);

flag = false;

}

}

if(flag){

break;//某趟冒泡没有交换则可以结束排序

}

}

System.out.println(Arrays.toString(data));

}

3、简单选择排序


n个元素进行简单选择排序,当排序第i个元素时,通过n-i次对元素间的比较,从n-i+1个元素中选出关键字最小的元素,并和第i个元素交换,当i=n时所有元素有序排列。

简单选择排序

/**

  • 简单选择排序

  • @param data

*/

public void selectSort(int[] data){

int i, j, k;

for(i=0;i<data.length-1;i++){

k = i;//k存放最小元素下标

for(j=i+1;j<data.length;j++){

if(data[j]<data[k]){

k = j;//记录当前最小元素的下标

}

}

if(k != i){//存在比data[i]更小元素,交换data[i]与data[k]

swap(data, i, k);

}

}

System.out.println(Arrays.toString(data));

}

4、希尔排序


希尔排序是对直接插入排序方法的改进。

其基本思想是:对待排序的n个元素,首先取d1(d1<n)作为分组间距,将所有距离为d1倍数的元素放在同一组中,由此将所有待排列元素分为d1组,在每个组内做直接插入排序;接着取d2(d2<d1)作为分组间距得到d2个组,组内进行直接插入排序…重复上述操作直到di=1,此时得到所有待排序元素分为一组且基本有序,进行直接插入排序可以得到最终有序排列的数组。

希尔排序

/**

  • 希尔排序

  • @param data

*/

public void shellSort(int[] data){

int i, j, k, s, tmp;

k = data.length;

int[] dist = new int[k/2];

i = 0;

do{

k = k / 2;

dist[i++] = k;

}while(k > 1);//得到每次分组的间距,直到1为止

for(i=0;(s = dist[i])>0;i++){//取分组间距

System.out.println(“分组间距:” + s + “,此次排序得到:”);

for(k=s;k<data.length;k++){//对每个分组内元素做直接插入排序

if(data[k] < data[k-s]){

tmp = data[k];

for(j=k-s;j>=0&&data[j]>tmp;j-=s){

data[j+s] = data[j];

}

data[j+s] = tmp;

}

}

System.out.println(Arrays.toString(data));

}

}

5、快速排序


快速排序的基本思想是:通过一趟排序将待排的元素划分为独立的两部分,成为前半区和后半区。前半区中的元素都不大于后半区中的元素。然后再分别对这两部分进行快速排序,进而使整个序列有序。

快速排序中一次划分的具体方法是:设待排序元素中的一个元素为枢轴元素pivot,另外设两个指针 i 和 j 分别指向序列的首尾位置。假设本次枢轴元素取i最初指向元素,则首先从j所指位置起向前搜索,找到第一个小于pivot的元素时,将该元素移到i所指的位置;然后从i所在位置开始向后搜索,找到第一个大于pivot的元素时将其移到j所指位置。重复该过程直到i等于j,将pivot复制到i和j指向位置。同理,若枢轴元素取j最初指向元素,则首先从i所指位置向后搜索。

如下图所示,对数组进行一次划分得到前半区[5,9,12,21]和后半区[23,76,32],再分别对两个分区进行快速排序,即可得到有序序列[5,9,12,21,23,32,76]。

快速排序的一次划分

快速排序被认为是在复杂度为O(nlogn)的排序方法中最好的一种,但是若初始序列元素有序或基本有序时,每次划分结果都会得到一个长度为0的分区,此时快速排序的性能退化为O(n²)。为了避免性能退化,一般会在选择枢轴元素时采用三数取中的方法。

三数取中:即在待排序数组中对首、中、尾三个元素进行大小比较,选择中间大小的元素作为枢轴元素。

三数取中

/**

  • 快速排序

  • @param data

*/

public void quickSort(int[] data, int low, int high){

if(low < high){

int loc = partition(data, low, high);//进行一次分区

quickSort(data, low, loc - 1);//对前半区快速排序

quickSort(data, loc + 1, high);//对后半区快速排序

}

}

/**

  • 一次划分后,得到数组以枢轴元素data[i]为界,前半区元素都不大于data[i],后半区元素都不小于data[i]

  • @param data

  • @param low

  • @param high

  • @return

*/

public int partition(int[] data, int low, int high){

getPivot(data, low, high);

int pivot = data[high-1];//枢轴元素

int i = low;

int j = high - 1;

while(i < j){

while(i < j && data[++i] <= pivot){}

data[j] = data[i];//data[i]大于pivot,移到后半区,此时原data[j]的值已保存在pivot或data[i]中

while(i < j && data[–j] >= pivot){}

data[i] = data[j];//data[j]小于pivot,移到前半区,此时原data[i]的值已保存在data[j]中

}

data[i] = pivot;

return i;

}

/**

  • 取首、中、尾三者中间大小元素,避免快速排序性能退化

  • @param data

  • @param low

  • @param high

*/

public void getPivot(int[] data, int left, int right){

int mid = (left + right) / 2;

//对三个元素按递增排序

if (data[left] > data[mid]) {

swap(data, left, mid);

}

if (data[left] > data[right]) {

swap(data, left, right);

}

if (data[right] < data[mid]) {

swap(data, right, mid);

}

//将枢轴元素放置在待排序数组后

swap(data, right-1, mid);

}

/**

  • 快速排序非递归

  • @param data

*/

public void quickSortNotRecur(int[] data, int low, int high){

//使用栈来实现递归的压栈出栈操作

Stack s = new Stack();

s.push(low);

s.push(high);

if(!s.empty()){

high = (Integer) s.pop();

low = (Integer) s.pop();

int loc = partition(data, low, high);//进行一次分区

s.push(loc+1);//后半区先进后出

s.push(high);

s.push(low);//前半区后进先出

s.push(loc-1);

}

}

6、堆排序


对待排列的n个元素组成的序列,将其看成一个完全二叉树,如果该二叉树中的任一非叶子节点的值均不小于(不大于)其左右子树节点,则该二叉树称为大根堆(小根堆),树的根节点(堆顶元素)是序列中最大(最小)的元素。

堆排序的基本思想是:对待非递减排列的序列首先建立一个初始堆,此时输出堆顶元素,即最大值元素,然后取最后一个叶子节点替代堆顶元素,并将剩下的元素重新构建为大根堆,再输出新堆的堆顶元素作为次大值元素…以此类推,直到所有的元素有序排列。

堆排序

/**

  • 堆排序

  • @param data

*/

public void heapSort(int[] data){

int i, n, tmp;

n = data.length;

for(i=n/2-1;i>=0;i–){//从n位置子节点所在子树开始向上调整整个数组为大根堆(构建初始堆)

heapAdjust(data, i, n-1);

}

for(i=n-1;i>0;i–){//从初始堆取堆顶(最大元素),对剩余元素重新构建大根堆

tmp = data[0];//取堆顶

data[0] = data[i];//将最末尾子节点交换到堆顶

data[i] = tmp;//当前最大值放到数组末尾

heapAdjust(data, 0, i-1);//剩余i-1个元素构建大根堆

}

System.out.println(Arrays.toString(data));

}

/**

  • 将待排序元素调整为大根堆

  • @param data

  • @param s

  • @param m

*/

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
img

复习的面试资料

这些面试全部出自大厂面试真题和面试合集当中,小编已经为大家整理完毕(PDF版)

  • 第一部分:Java基础-中级-高级

image

  • 第二部分:开源框架(SSM:Spring+SpringMVC+MyBatis)

image

  • 第三部分:性能调优(JVM+MySQL+Tomcat)

image

  • 第四部分:分布式(限流:ZK+Nginx;缓存:Redis+MongoDB+Memcached;通讯:MQ+kafka)

image

  • 第五部分:微服务(SpringBoot+SpringCloud+Dubbo)

image

  • 第六部分:其他:并发编程+设计模式+数据结构与算法+网络

image

进阶学习笔记pdf

  • Java架构进阶之架构筑基篇(Java基础+并发编程+JVM+MySQL+Tomcat+网络+数据结构与算法

image

  • Java架构进阶之开源框架篇(设计模式+Spring+SpringMVC+MyBatis

image

image

image

  • Java架构进阶之分布式架构篇 (限流(ZK/Nginx)+缓存(Redis/MongoDB/Memcached)+通讯(MQ/kafka)

image

image

image

  • Java架构进阶之微服务架构篇(RPC+SpringBoot+SpringCloud+Dubbo+K8s)

image

image

va架构进阶之开源框架篇(设计模式+Spring+SpringMVC+MyBatis)**

[外链图片转存中…(img-rqFoXlW2-1711053343120)]

[外链图片转存中…(img-phpWAsmF-1711053343121)]

[外链图片转存中…(img-biw11fDC-1711053343121)]

  • Java架构进阶之分布式架构篇 (限流(ZK/Nginx)+缓存(Redis/MongoDB/Memcached)+通讯(MQ/kafka)

[外链图片转存中…(img-f9ouVtzc-1711053343121)]

[外链图片转存中…(img-cvsh0WY0-1711053343122)]

[外链图片转存中…(img-WHgAYSet-1711053343122)]

  • Java架构进阶之微服务架构篇(RPC+SpringBoot+SpringCloud+Dubbo+K8s)

[外链图片转存中…(img-DvD9gOkz-1711053343122)]

[外链图片转存中…(img-cGeGXWuI-1711053343123)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 22
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值