百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

java实现10种排序算法

lipiwang 2025-05-23 18:24 3 浏览 0 评论

1.冒泡排序(Bubble Sort)

import java.util.Arrays;

//冒泡排序

public class BubbleSort_01 {

public static void main(String[] args) {

int a[]={3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};

//记录比较次数

int count=0;

//i=0,第一轮比较

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

//第一轮,两两比较

for (int j = 0; j < a.length-1-i; j++) {

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

int temp=a[j];

a[j]=a[j+1];

a[j+1]=temp;

}

count++;

}

}

System.out.println(Arrays.toString(a));//[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]

System.out.println("一共比较了:"+count+"次");//一共比较了:105次

}

}

冒泡排序的优化1:

import java.util.Arrays;

public class BubbleSort1_01 {

public static void main(String[] args) {

int a[]={3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};

int count=0;

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

boolean flag=true;

for (int j = 0; j < a.length-1-i; j++) {

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

int temp=a[j];

a[j]=a[j+1];

a[j+1]=temp;

flag=false;

}

count++;

}

if (flag) {

break;

}

}

System.out.println(Arrays.toString(a));// [2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]

System.out.println("一共比较了:"+count+"次");//一共比较了:95次

}

}

2.选择排序(Select Sort)

import java.util.Arrays;

//选择排序:先定义一个记录最小元素的下标,然后循环一次后面的,找到最小的元素,最后将他放到前面排序好的序列。

public class SelectSort_02 {

public static void main(String[] args) {

int a[]={3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};

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

int index=i;//标记第一个为待比较的数

for (int j = i+1; j < a.length; j++) { //然后从后面遍历与第一个数比较

if (a[j]<a[index]) { //如果小,就交换最小值

index=j;//保存最小元素的下标

}

}

//找到最小值后,将最小的值放到第一的位置,进行下一遍循环

int temp=a[index];

a[index]=a[i];

a[i]=temp;

}

System.out.println(Arrays.toString(a));//[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]

}

}

3.插入排序(Insert Sort)

import java.util.Arrays;

//插入排序:定义一个待插入的数,再定义一个待插入数的前一个数的下标,然后拿待插入数与前面的数组一一比较,最后交换。

public class InsertSort_03 {

public static void main(String[] args) {

int a[]={3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};

for (int i = 0; i < a.length; i++) { //长度不减1,是因为要留多一个位置方便插入数

//定义待插入的数

int insertValue=a[i];

//找到待插入数的前一个数的下标

int insertIndex=i-1;

while (insertIndex>=0 && insertValue <a[insertIndex]) {//拿a[i]与a[i-1]的前面数组比较

a[insertIndex+1]=a[insertIndex];

insertIndex--;

}

a[insertIndex+1]=insertValue;

}

System.out.println(Arrays.toString(a));//[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]

}

}

4.希尔排序(Shell Sort)

import java.util.Arrays;

//希尔排序:插入排序的升级

public class ShellSort_04 {

public static void main(String[] args) {

int a[]={3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};

int count=0;//比较次数

for (int gap=a.length / 2; gap > 0; gap = gap / 2) {

//将整个数组分为若干个子数组

for (int i = gap; i < a.length; i++) {

//遍历各组的元素

for (int j = i - gap; j>=0; j=j-gap) {

//交换元素

if (a[j]>a[j+gap]) {

int temp=a[j];

a[j]=a[j+gap];

a[j+gap]=temp;

count++;

}

}

}

}

System.out.println(count);//16

System.out.println(Arrays.toString(a));//[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]

}

}

5.快速排序(Quick Sort)

import java.util.Arrays;

//快速排序:冒泡排序的升华版

public class QuickSort_05 {

public static void main(String[] args) {

//int a[]={50,1,12,2};

int a[]={3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};

quicksort(a,0,a.length-1);

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

}

private static void quicksort(int[] a, int low, int high) {

int i,j;

if (low>high) {

return;

}

i=low;

j=high;

int temp=a[low];//基准位,low=length时,会报异常,
java.lang.ArrayIndexOutOfBoundsException: 4 ,所以必须在if判断后面,就跳出方法。

while(i<j){

//先从右边开始往左递减,找到比temp小的值才停止

while ( temp<=a[j] && i<j) {

j--;

}

//再看左边开始往右递增,找到比temp大的值才停止

while ( temp>=a[i] && i<j) {

i++;

}

//满足 i<j 就交换,继续循环while(i<j)

if (i<j) {

int t=a[i];

a[i]=a[j];

a[j]=t;

}

}

//最后将基准位跟 a[i]与a[j]相等的位置,进行交换,此时i=j

a[low]=a[i];

a[i]=temp;

//左递归

quicksort(a, low, j-1);

//右递归

quicksort(a, j+1, high);

}

}

6.归并排序(Merge Sort)

import java.util.Arrays;

//归并排序

public class MergeSort_06 {

public static void main(String[] args) {

int a[]={3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};

//int a[]={5,2,4,7,1,3,2,2};

int temp[]=new int[a.length];

mergesort(a,0,a.length-1,temp);

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

}

private static void mergesort(int[] a, int left, int right, int[] temp) {

//分解

if (left<right) {

int mid=(left+right)/2;

//向左递归进行分解

mergesort(a, left, mid, temp);

//向右递归进行分解

mergesort(a, mid+1, right, temp);

//每分解一次便合并一次

merge(a,left,right,mid,temp);

}

}

/**

*

* @param a 待排序的数组

* @param left 左边有序序列的初始索引

* @param right 右边有序序列的初始索引

* @param mid 中间索引

* @param temp 做中转的数组

*/

private static void merge(int[] a, int left, int right, int mid, int[] temp) {

int i=left; //初始i,左边有序序列的初始索引

int j=mid+1;//初始化j,右边有序序列的初始索引(右边有序序列的初始位置即中间位置的后一位置)

int t=0;//指向temp数组的当前索引,初始为0


//先把左右两边的数据(已经有序)按规则填充到temp数组

//直到左右两边的有序序列,有一边处理完成为止

while (i<=mid && j<=right) {

//如果左边有序序列的当前元素小于或等于右边的有序序列的当前元素,就将左边的元素填充到temp数组中

if (a[i]<=a[j]) {

temp[t]=a[i];

t++;//索引向后移

i++;//i后移

}else {

//反之,将右边有序序列的当前元素填充到temp数组中

temp[t]=a[j];

t++;//索引向后移

j++;//j后移

}

}

//把剩余数据的一边的元素填充到temp中

while (i<=mid) {

//此时说明左边序列还有剩余元素

//全部填充到temp数组

temp[t]=a[i];

t++;

i++;

}

while (j<=right) {

//此时说明左边序列还有剩余元素

//全部填充到temp数组

temp[t]=a[j];

t++;

j++;

}

//将temp数组的元素复制到原数组

t=0;

int tempLeft=left;

while (tempLeft<=right) {

a[tempLeft]=temp[t];

t++;

tempLeft++;

}

}

}

7.堆排序(Heap Sort)

public class Heap_Sort_07 {

public static void main(String[] args) {

int a[]={3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};

sort(a);

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

}

public static void sort(int[] arr) {

int length = arr.length;

//构建堆

buildHeap(arr,length);

for ( int i = length - 1; i > 0; i-- ) {

//将堆顶元素与末位元素调换

int temp = arr[0];

arr[0] = arr[i];

arr[i] = temp;

//数组长度-1 隐藏堆尾元素

length--;

//将堆顶元素下沉 目的是将最大的元素浮到堆顶来

sink(arr, 0,length);

}

}

private static void buildHeap(int[] arr, int length) {

for (int i = length / 2; i >= 0; i--) {

sink(arr,i, length);

}

}


private static void sink(int[] arr, int index, int length) {

int leftChild = 2 * index + 1;//左子节点下标

int rightChild = 2 * index + 2;//右子节点下标

int present = index;//要调整的节点下标

//下沉左边

if (leftChild < length && arr[leftChild] > arr[present]) {

present = leftChild;

}

//下沉右边

if (rightChild < length && arr[rightChild] > arr[present]) {

present = rightChild;

}

//如果下标不相等 证明调换过了

if (present != index) {

//交换值

int temp = arr[index];

arr[index] = arr[present];

arr[present] = temp;

//继续下沉

sink(arr, present, length);

}

}

}

8.计数排序 (Count Sort)

算法的步骤如下:

找出待排序的数组array中最大的元素max

统计数组中每个值为 i 的元素出现的次数,存入数组 count 的第 i 项

对所有的计数累加(从 count中的第一个元素开始,每一项和前一项相加)

反向填充目标数组:将每个元素 i 放在新数组的第 count [i] 项,每放一个元素就将 count [i] 减去

import java.util.Arrays;

public class CountSort_08 {

public static void main(String[] args) {

int[] array = { 4, 2, 2, 8, 3, 3, 1 };

// 找到数组中最大的值 ---> max:8

int max = findMaxElement(array);

int[] sortedArr = countingSort(array, max + 1);

System.out.println("计数排序后的数组: " + Arrays.toString(sortedArr));

}

private static int findMaxElement(int[] array) {

int max = array[0];

for (int val : array) {

if (val > max)

max = val;

}

return max;

}

private static int[] countingSort(int[] array, int range) { //range:8+1

int[] output = new int[array.length];

int[] count = new int[range];

//初始化: count1数组

for (int i = 0; i < array.length; i++) {

count[array[i]]++;

}

//计数: count2数组,累加次数后的,这里用count2区分

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

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

}

//排序:最后数组

for (int i = 0; i < array.length; i++) {

output[count[array[i]] - 1] = array[i];

count[array[i]]--;

}

return output;

}

}

9.桶排序(Bucket Sort)

桶排序可以看成是计数排序的升级版,它将要排的数据分到多个有序的桶里,每个桶里的数据再单独排序,再把每个桶的数据依次取出,即可完成排序。
桶排序:将值为i的元素放入i号桶,最后依次把桶里的元素倒出来。

思路:

设置一个定量的数组当作空桶子。

寻访序列,并且把项目一个一个放到对应的桶子去。

对每个不是空的桶子进行排序。

从不是空的桶子里把项目再放回原来的序列中。

public class BucketSort_09 {

public static void sort(int[] arr){

//最大最小值

int max = arr[0];

int min = arr[0];

int length = arr.length;

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

if(arr[i] > max) {

max = arr[i];

} else if(arr[i] < min) {

min = arr[i];

}

}

//最大值和最小值的差

int diff = max - min;

//桶列表

ArrayList<ArrayList<Integer>> bucketList = new ArrayList<>();

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

bucketList.add(new ArrayList<>());

}

//每个桶的存数区间

float section = (float) diff / (float) (length - 1);

//数据入桶

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

//当前数除以区间得出存放桶的位置 减1后得出桶的下标

int num = (int) (arr[i] / section) - 1;

if(num < 0){

num = 0;

}

bucketList.get(num).add(arr[i]);

}

//桶内排序

for(int i = 0; i < bucketList.size(); i++){

//jdk的排序速度当然信得过

Collections.sort(bucketList.get(i));

}

//写入原数组

int index = 0;

for(ArrayList<Integer> arrayList : bucketList){

for(int value : arrayList){

arr[index] = value;

index++;

}

}

}

}

10.基数排序(Raix Sort)

我们假设有一个待排序数组[53,3,542,748,14,214],那么如何使用基数排序对其进行排序呢?

首先我们有这样的十个一维数组,在基数排序中也叫桶。用桶排序实现。

第一轮,以元素的个位数进行区分:[542,53,3,14,214,748]

第二轮,以元素的十位数进行区分:[3,14,214,542,748,53]

第三轮,以元素的百位数进行区分:[3,14,53,214,542,748]

import java.util.Arrays;

public class RaixSort_10 {

public static void main(String[] args) {

int[] arr = { 53, 3, 542, 748, 14, 214 };

// 得到数组中最大的数

int max = arr[0];// 假设第一个数就是数组中的最大数

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

if (arr[i] > max) {

max = arr[i];

}

}

// 得到最大数是几位数

// 通过拼接一个空串将其变为字符串进而求得字符串的长度,即为位数

int maxLength = (max + "").length();

// 定义一个二维数组,模拟桶,每个桶就是一个一维数组

// 为了防止放入数据的时候桶溢出,我们应该尽量将桶的容量设置得大一些

int[][] bucket = new int[10][arr.length];

// 记录每个桶中实际存放的元素个数

// 定义一个一维数组来记录每个桶中每次放入的元素个数

int[] bucketElementCounts = new int[10];

// 通过变量n帮助取出元素位数上的数

for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {

for (int j = 0; j < arr.length; j++) {

// 针对每个元素的位数进行处理

int digitOfElement = arr[j] / n % 10;

// 将元素放入对应的桶中

// bucketElementCounts[digitOfElement]就是桶中的元素个数,初始为0,放在第一位

bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];

// 将桶中的元素个数++

// 这样接下来的元素就可以排在前面的元素后面

bucketElementCounts[digitOfElement]++;

}

// 按照桶的顺序取出数据并放回原数组

int index = 0;

for (int k = 0; k < bucket.length; k++) {

// 如果桶中有数据,才取出放回原数组

if (bucketElementCounts[k] != 0) {

// 说明桶中有数据,对该桶进行遍历

for (int l = 0; l < bucketElementCounts[k]; l++) {

// 取出元素放回原数组

arr[index++] = bucket[k][l];

}

}

// 每轮处理后,需要将每个bucketElementCounts[k]置0

bucketElementCounts[k] = 0;

}

}

System.out.println(Arrays.toString(arr));//[3, 14, 53, 214, 542, 748]

}

}

基数排序是用空间换时间的经典算法,当数据足够多时,达到几千万级别时内存空间可能不够用了,发生堆内存溢出

私信666领取资料

相关推荐

httpclient+jsoup实现小说线上采集阅读

前言  用过老版本UC看小说的同学都知道,当年版权问题比较松懈,我们可以再UC搜索不同来源的小说,并且阅读,那么它是怎么做的呢?下面让我们自己实现一个小说线上采集阅读。(说明:仅用于技术学习、研究) ...

Python3+requests+unittest接口自动化测试实战

一、Requests介绍RequestsisanelegantandsimpleHTTPlibraryforPython,builtforhumanbeings.翻译过来就是...

授权码 + PKCE 模式|OIDC &amp; OAuth2.0 认证协议最佳实践系列【03】

在上一篇文章中,我们介绍了OIDC授权码模式,本次我们将重点围绕授权码+PKCE模式(AuthorizationCodeWithPKCE)进行介绍,从而让你的系统快速具备接入用户认...

JWT 在 Java Web 开发中的奇妙应用

JWT在JavaWeb开发中的奇妙应用在当今的互联网世界里,安全始终是一个绕不开的话题。而当我们谈论到Web应用的安全性时,认证和授权绝对是其中的核心部分。说到这,我忍不住要给大家讲个笑话...

动手操作:一个 OAuth 2 应用程序(2) - 配置 Keycloak 为授权服务器

接上一篇《动手操作:一个OAuth2应用程序(1)-应用程序场景》进行场景分析后,本篇就开始动手实现授权服务器。在本文中,我们将Keycloak配置为系统的授权服务器(图3)。...

JSON Web Token是什么?

JSONWebToken(缩写JWT)是目前最流行的跨域认证解决方案。传统的session认证http协议本身是一种无状态的协议,而这就意味着如果用户向我们的应用提供了用户名和密码来进行用户认证...

Keycloak Servlet Filter Adapter使用

KeycloakClientAdapters简介Keycloakclientadaptersarelibrariesthatmakeitveryeasytosecurea...

使用JWT生成token

一、使用JWT进行身份验证1、传统用户身份验证Internet服务无法与用户身份验证分开。一般过程如下:用户向服务器发送用户名和密码。验证服务器后,相关数据(如用户角色,登录时间等)将保存在当前会话中...

在word中通过VBA调用百度翻译API在线翻译

一天的时间,借助各种AI终于解决了这个问题:在word中通过VBA调用百度翻译API进行在线翻译。给我的word又添加了一项神技。先上代码:Sub宏5()''宏5宏Dimapp...

API 安全之认证鉴权

作者:半天前言API作为企业的重要数字资源,在给企业带来巨大便利的同时也带来了新的安全问题,一旦被攻击可能导致数据泄漏重大安全问题,从而给企业的业务发展带来极大的安全风险。正是在这样的背景下,Ope...

用WordPress建站哪些插件会拖慢速度影响排名?

你是否发现网站加载总慢半拍,SEO排名死活上不去?八成是插件惹的祸!80%的站长不知道,WordPress插件用错类型或配置不当,分分钟让网站速度暴跌,爬虫抓取效率直接砍半。缓存插件没装对,越用越卡你...

JavaScript报错了?不要慌!怎么看怎么处理都在这里

在开发中,有时,我们花了几个小时写的JS代码,在游览器调试一看,控制台一堆红,瞬间一万头草泥马奔腾而来。至此,本文主要记录JS常见的一些报错类型,以及常见的报错信息,分析其报错原因,并给予处理...

跨站脚本攻击(四)
跨站脚本攻击(四)

04XSS漏洞挖掘技巧4.1常见的绕过姿势实际应用中web程序往往会通过一些过滤规则来阻止带有恶意代码的用户输入被显示,但由于HTML语言的松散性和各种标签的不同优先级,使得我们绕过过滤规则成为了可能。4.1.1利用大小写绕过HTML标签...

2025-05-24 15:21 lipiwang

WAF-Bypass之SQL注入绕过思路总结

过WAF(针对云WAF)寻找真实IP(源站)绕过如果流量都没有经过WAF,WAF当然无法拦截攻击请求。当前多数云WAF架构,例如百度云加速、阿里云盾等,通过更改DNS解析,把流量引入WAF集群,流量经...

Springboot之登录模块探索(含Token,验证码,网络安全等知识)

简介登录模块很简单,前端发送账号密码的表单,后端接收验证后即可~淦!可是我想多了,于是有了以下几个问题(里面还包含网络安全问题):1.登录时的验证码2.自动登录的实现3.怎么维护前后端登录状态在这和大...

取消回复欢迎 发表评论: