常见排序查询算法Java代码实现

1. 排序算法代码实现

/*** ascending sort*  外层循环边界条件:总共需要冒泡的轮数--每一轮都将最大或最小的数冒泡到最后*  内层循环边界条件:冒泡数字移动的边界--最终数字需冒泡到此处*  时间复杂度:O(n^2)* @param arr*/
public static void bubbleSort(int[] arr) {if (arr == null) {throw new RuntimeException("Input arr is null!");}for(int i = 0; i < arr.length - 1; i++) {for(int j = 0; j < arr.length - 1 - i; j++) {				 //冒泡:相邻两数比较,大的向后冒if(arr[j] > arr[j+1]) {int temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;}}}
}/*** 每次都将未排序数组中的最大或最小元素找出来和第一个元素交换位置*  时间复杂度:O(n^2)* @param arr*/
public static void selectSort(int[] arr) {if (arr == null) {throw new RuntimeException("Input arr is null!");}for(int i = 0; i < arr.length - 1; i++) {//寻找最小元素的下标,避免频繁交换数组int min = i;for(int j = i + 1; j < arr.length; j++) {if (arr[j] < arr[min]) {min = j;}}//将最小的元素交换到未排序数组的最前面int temp = arr[i];arr[i] = arr[min];arr[min] = temp;}
}/*** 插入排序:顺次从数组中选择一个数,插入到前面已排序的数组中* 时间复杂度:O(n)~O(n^2)* @param arr*/
public static void insertSort(int[] arr) {if (arr == null) {throw new RuntimeException("Input arr is null!");}for(int i = 1; i < arr.length; i++) {int value = arr[i];//插入的位置int j = 0;//循环i前面的数,若值比插入的值大,则顺次向后移动for (j = i - 1; j >= 0; j--) {if(arr[j] > value) {arr[j+1] = arr[j];} else {break;}}arr[j+1]=value;}
}/*** 	希尔排序:插入排序的改进版,也称缩小增量排序** @param arr*/
public static void shellSort(int[] arr) {if (arr == null) {throw new RuntimeException("Input arr is null!");}int length = arr.length;//区间int gap = 1;while(gap < length) {gap = gap * 3 +1;}while(gap > 0) {for(int i = gap; i < length; i++) {int tmp = arr[i];int j = i -gap;//跨区间排序while(j >= 0 && arr[j] > tmp) {arr[j+gap] = arr[j];j -= gap;}arr[j + gap] = tmp;}gap = gap / 3;}
}/*** 	归并排序--核心为分治法*	时间复杂度O(nlogn)* @param arr*/
public static void mergeSort(int[] arr) {if (arr == null) {throw new RuntimeException("Input arr is null!");}int[] tmpArr = new int[arr.length];mSort(arr,tmpArr, 0, arr.length - 1);
}private static void mSort(int[] arr, int[] tmpArr, int startIndex, int endIndex) {//边界条件:数组已不可再拆if (endIndex <= startIndex) {return;}//将数组对拆为前后两个数组int middleIndex = startIndex + (endIndex - startIndex)/2;mSort(arr, tmpArr, startIndex, middleIndex);mSort(arr, tmpArr, middleIndex + 1, endIndex);merge(arr, tmpArr, startIndex, middleIndex, endIndex);
}private static void merge(int[] arr, int[] tmpArr, int startIndex, int middleIndex, int endIndex) {//将要合并的数组复制到临时数组for (int i = startIndex; i <= endIndex; i++) {tmpArr[i] = arr[i];}//左边数组起始下标int left = startIndex;//右边数组起始下标int right = middleIndex + 1;for(int k = startIndex; k <= endIndex; k++) {	if (left > middleIndex) {arr[k] = tmpArr[right++];} else if (right > endIndex) {arr[k] = tmpArr[left++];} else if (tmpArr[left] < tmpArr[right]) {arr[k] = tmpArr[left++];} else {arr[k] = tmpArr[right++];}			}
}/*** 	快速排序:随机选取一个参考值,将比参考值小的数移到数组前段,大的值移到后段* 	以参考值为临界点递归拆分数组直至数组不能拆分,此时数组本身已排好序* 	快速排序时间复杂度为O(nlogn),对于逆序数组复杂度退化为O(n^2),为了避免极端情况,可随机选取参考值* @param arr*/
public static void quickSort(int[] arr) {if (arr == null) {throw new RuntimeException("Input arr is null!");}qSort(arr , 0, arr.length - 1);		
}private static void qSort(int[] arr, int startIndex, int endIndex) {// 设置边界条件if (endIndex <= startIndex) {return;}// 将数组按参考值整理成比参考值小的前段和比参考值大的后段,返回参考值的位置int refIndex = partition(arr, startIndex, endIndex);// 参考值已确定排序后的位置,不参与数组拆分if (refIndex > startIndex) {qSort(arr, startIndex, refIndex - 1);}if (endIndex > refIndex) {qSort(arr, refIndex + 1, endIndex);}			
}
private static int partition(int[] arr, int startIndex, int endIndex) {// 将数组中refValue的值与最后一个数交换,随机选取参考值可避免时间复杂度退化为O(n^2)int refIndex = startIndex + new Random().nextInt(endIndex - startIndex + 1);// 深坑,当两个数指向同一个时,会影响异或结果if (refIndex != endIndex) {arr[endIndex] = arr[endIndex] ^ arr[refIndex];arr[refIndex] = arr[endIndex] ^ arr[refIndex];arr[endIndex] = arr[endIndex] ^ arr[refIndex];}// 分组下标int partitionIndex = startIndex - 1;// 数组最后一个值为参考值,不参与循环for (int dataIndex = startIndex; dataIndex < endIndex; dataIndex++) {// 与参考值进行比较,若比参考值小,则移动到数组前面if ((arr[dataIndex] < arr[endIndex]) ) {// 始终指向最后一个确定比参考值小的值++partitionIndex;// 如果当前数据的位置与参考下标不一致,将此值与参考下标指向的值交换,保证小的值交换到前面if (partitionIndex != dataIndex) {arr[dataIndex] = arr[dataIndex] ^ arr[partitionIndex] ;arr[partitionIndex] = arr[dataIndex] ^ arr[partitionIndex];arr[dataIndex] = arr[dataIndex] ^ arr[partitionIndex];} }}// 将参考值交换到指定位置++partitionIndex;if (partitionIndex != endIndex) {arr[endIndex] = arr[endIndex] ^ arr[partitionIndex] ;arr[partitionIndex] = arr[endIndex] ^ arr[partitionIndex];arr[endIndex] = arr[endIndex] ^ arr[partitionIndex];}return partitionIndex; }/*** 堆排序--最大堆实现* 时间复杂度O(nlogn)* @param arr*/ public static void heapSort(int[] arr) {if (arr == null) {throw new RuntimeException("Input arr is null!");}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 rigthChild = 2 * index + 2;//要调整的节点下标int present = index;//下沉左边if (leftChild < length && arr[leftChild] > arr[present]) {present = leftChild;}//下沉右边if (rigthChild < length && arr[rigthChild] > arr[present]) {present = rigthChild;}//如果下标不相等,证明调换过了if (present != index) {//交换值int temp = arr[index];arr[index] = arr[present];arr[present] = temp;//继续下沉sink(arr, present, length);} }/*** 计数排序--时间复杂度为O(n+m),空间大小取决于数组值,时间复杂度为O(n)* 问题点:数组中不能有负数,否则会抛出越界异常* @param arr*/ public static void countSort(int[] arr) {if (arr == null) {throw new RuntimeException("Input arr is null!");}//找出数组中的最大值int max = arr[0];for(int i = 1; i < arr.length; i++) {if (arr[i] < 0) {throw new RuntimeException("Cannot use countsort! Array contains negative number.");}if (max < arr[i]) {max = arr[i];}}//利用最大值构建一个数组,用空间换时间int[] countArr = new int[max + 1];//计数for (int i = 0; i < arr.length; i++) {countArr[arr[i]]++;}int index = 0;for (int i = 0; i < countArr.length; i++) {while (countArr[i] > 0) {arr[index++] = i;countArr[i]--;}} }/*** 桶排序--类似于Hash分桶策略* 良好的分桶策略可实现O(n)时间复杂度* @param arr*/ public static void bucketSort(int[] arr) {if (arr == null) {throw new RuntimeException("Input arr is null!");}//最大最小值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++) {Collections.sort(bucketList.get(i));}//写入数据int index = 0;for (ArrayList<Integer> arrayList: bucketList) {for (int value : arrayList) {arr[index] = value;index++;}} }/*** 基数排序* @param arr*/ public static void radixSort(int[] arr) {if (arr == null) {throw new RuntimeException("Input arr is null!");}int length = arr.length;//最大值int max = arr[0];for(int i = 0;i < length;i++){if(arr[i] > max){max = arr[i];}}//当前排序位置int location = 1;//桶列表ArrayList<ArrayList<Integer>> bucketList = new ArrayList<>();//长度为10 装入余数0-9的数据for(int i = 0; i < 10; i++){bucketList.add(new ArrayList<>());}while(true){//判断是否排完int dd = (int)Math.pow(10, (location - 1));if(max < dd){break;}//数据入桶for(int i = 0; i < length; i++){//计算余数 放入相应的桶int number = ((arr[i] / dd) % 10);bucketList.get(number).add(arr[i]);}//写回数组int nn = 0;for (int i=0;i<10;i++){int size = bucketList.get(i).size();for(int ii = 0;ii < size;ii ++){arr[nn++] = bucketList.get(i).get(ii);}bucketList.get(i).clear();}location++;} }

  2. 查询算法代码实现

/***    顺序查找,即为遍历数组,时间复杂度为O(n)* @param arr* @param value* @return*/
public static int sequentialSearch(int[] arr, int value) {if (arr == null) {throw new RuntimeException("Input arr is null!");}for (int i = 0; i < arr.length; i++) {if (arr[i] == value) {return i;}}return -1;
}/***    二分查找针对以升序排列的数组进行,每次取数组的中间值进行查找*    时间复杂度为O(logn)* @param arr* @param value* @return*/
public static int binarySearch(int[] arr, int value) {if (arr == null) {throw new RuntimeException("Input arr is null!");}int low = 0;int high = arr.length - 1;int mid = 0;while (low <= high) {mid = (low + high)/2;if (arr[mid] == value) {return mid;} else if (arr[mid] > value) {high = mid -1;} else {low = mid + 1;}}return -1;
}/***     二分查找--递归实现* @param arr    待查询数组* @param value    查找目标值* @param low    数组起始下标* @param high    数组结束下标* @return    目标值的下标*/
public static int binarySearchByRecursion(int[] arr, int value, int low, int high) {if (arr == null) {throw new RuntimeException("Input arr is null!");}int mid = low + (high -low)/2;if (low == high && arr[mid] != value) {return -1;}if (arr[mid] == value) {return mid;} else if (arr[mid] > value) {return binarySearchByRecursion(arr, value, low, mid - 1);} else {return binarySearchByRecursion(arr, value, mid + 1, high);}
}/***     插值查找--递归实现,原理与二分查找类似,按目标值的大小计算在数组中的权重,适用于均有有序的数组* @param arr    待查询数组* @param value    查找目标值* @param low    数组起始下标* @param high    数组结束下标* @return    目标值的下标*/
public static int insertionSearch(int[] arr, int value, int low, int high) {if (arr == null) {throw new RuntimeException("Input arr is null!");}// 按目标值与最小值的差估算插值下标的位置int mid = low + ((value - arr[low]) / (arr[high] - arr[low])) * (high -low);if (low == high && arr[mid] != value) {return -1;}if (arr[mid] == value) {return mid;} else if (arr[mid] > value) {return binarySearchByRecursion(arr, value, low, mid - 1);} else {return binarySearchByRecursion(arr, value, mid + 1, high);}
}

 

转载于:https://www.cnblogs.com/beichenroot/p/11122212.html

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

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

相关文章

java jsp 传递参数的方法,jsp传参方法小结

一、jsp页面到jsp页面##1.从a.jsp传递//将参数值为aaa&#xff0c;参数名test的参数传递到b.jsp页面中2.在b.jsp接收System.out.println("test的值是"test); %>二、jsp页面到servlet##1.首先需要新建一个Servlet&#xff0c;包的层次结构如下&#xff1a;demo--sr…

工作403-修改input里面的文本框值

1.style中需要作如下修改<style>input::-webkit-input-placeholder {/* placeholder颜色 */color: #aab2bd;/* placeholder字体大小 */font-size: 12px;} </style>2.HTML中的代码如<input type"text" placeholder"输入你想要查找的内容" …

Microsoft Expression Studio 4 Ultimate 中文版发布

Expression Studio Ultimate 是供生成网站以及 Windows 客户端应用程序和丰富媒体内容的专业设计人员使用的一系列工具&#xff0c;可以将创作人员引领到一个全新的创作天地。无论您是准备设计基于标准的网站&#xff0c;还是设计内容精美&#xff0c;令人赏心悦目的桌面或者 S…

Struts2基础

1.Struts2 Actions动作 Actions是Struts2框架的核心&#xff0c;因为它们适用于任何MVC&#xff08;Model View Controller&#xff09;框架。 每个URL映射到特定的action&#xff0c;其提供处理来自用户的请求所需的处理逻辑。但action还有另外两个重要的功能。 首先&#xf…

工作404-判断浏览器函数

// 判断浏览器函数if ((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {} else {window.location.href "../product_new.html&qu…

WebService简单示例

记录一下&#xff0c;以备后用&#xff1a;代码usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Web;usingSystem.Web.Services;usingSystem.Web.Services.Protocols;namespaceNiunan.ZZ.JKDA.Web.webservice{ ///<summary>///GGService 的…

php server 性能,PHP中:$_SERVER[‘REQUEST_TIME’]和 time()有什么区别,那个性能快!...

简单的说time()与$_SERVER["REQUEST_TIME"]都是获得时间的&#xff0c;但time返回当前的 Unix 时间戳而$_SERVER["REQUEST_TIME"]得到请求开始时的时间戳&#xff0c;稍有区别。1. time() 获取当前的系统时间戳inttime( void ) :返回自从 Unix 纪元(格林威…

Delphi捕捉DLL执行所抛出的异常。

先来说一下我如何写我的Dll文件的。 先看代码&#xff1a; 代码 librarypub_form;usesSysUtils, Classes, Windows, Forms, Parameter_Object, frm_LoginU in..\公用库单元\frm_LoginU.pas{frm_Login}, pub_Event in..\公用库单元\pub_Event.pas, Dll_LIB_ConstU in..\公…

docker版本Mysql安装

docker部署mysql 1. 下载 [rootlocalhost my.Shells]# ./dockerStart.sh start or stop start Redirecting to /bin/systemctl start docker.service [rootlocalhost my.Shells]# docker pull mysql Using default tag: latest Trying to pull repository docker.io/library/…

matlab 左上角,matlab – 访问’uitable`的左上角

在uitable中,我想访问行标签上方的单元格以及列标签的左侧.我想在该领域加上一些文字.可以这样做吗&#xff1f;最佳答案 简短的回答是肯定的,但这有点痛苦.您可以添加文本uicontrol并正确定位.一个功能的例子&#xff1a;% Dummy figure and tablef figure;d gallery(intege…

eclipse MyEclipse中安装 spket插件 js文件内容字体变小解决方案

在 eclipse 、 MyEclipse 中用 Spket 插件打开 js 文件后&#xff0c;发现字体非常小。&#xff08;在每次重启eclipse时会出现&#xff09;这个时候你只需要找到 Window->General->Appearance->Colors and Fonts ->Basic-Text Font ,点击右边的change&…

planning algorithms chapter 2

planning algorithms chapter 2 :Discrete Planning 离散可行规划导论 问题定义 在离散规划中&#xff0c;状态是“可数”的&#xff0c;有限的。 离散可行规划: 非空状态空间 X对于每个状态 x&#xff0c;存在一个有限的动作空间 U(x)对于每个状态和动作空间&#xff0c;存在状…

前端手动封装数组的foreach,map,filter,every,some,Reduce,reduceRight方法

我是歌谣 放弃很容易 但坚持一定很酷 公众号小歌谣 谢谢关注 前言 Foreach Array.prototype.myForEach function (cb) {var _arr this;var _len _arr.length;var _arg2 arguments[1] || window;for (var i 0; i < _len; i ) {cb.apply(_arg2, [_arr[i], i, _arr]);} …

[html] a标签的默认事件禁用后,如何实现跳转?

[html] a标签的默认事件禁用后&#xff0c;如何实现跳转&#xff1f; 给a标签添加点击事件利用 location.href 进行跳转个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面…

锤子剪刀布pat-1018

题目描述 大家应该都会玩“锤子剪刀布”的游戏&#xff1a;现给出两人的交锋记录&#xff0c;请统计双方的胜、平、负次数&#xff0c;并且给出双方分别出什么手势的胜算最大。 输入描述: 输入第1行给出正整数N&#xff08;<105&#xff09;&#xff0c;即双方交锋的次数。随…

mda.helper.php,dedecms后台更新缓慢甚至卡死怎么办

问题描述&#xff1a;如果我们在使用织梦程序(2018-01-09)&#xff0c;有可能会遇到后台更新网站、更新文档HTML、添加文档卡死的问题。该如何解决呢&#xff1f;(学习视频分享&#xff1a;编程视频)解决方法&#xff1a;如果你正在用的是最新版的织梦程序(2018-01-09)&#xf…

关于开心网的服务器

1.开心网的主站采用了DNS轮询技术&#xff0c;所谓DNS轮询&#xff0c;就是一个域名对应几条A记录&#xff0c;如开心网的主站有6台服务器DNS轮询有一个缺点&#xff0c;如果域名所指向的某一个台服务器或几台服务器出现了问题&#xff08;如Web服务器停止服务)&#xff0c;则D…

[html] 如何禁用掉a标签的默认事件?

[html] 如何禁用掉a标签的默认事件&#xff1f; a onclick"prevent" function prevent(e) { e.preventDefault(); }个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关…

PHP3.2.3 where or,WHERE · ThinkPHP3.2.3完全开发手册 · 看云

where方法的用法是ThinkPHP查询语言的精髓&#xff0c;也是ThinkPHP ORM的重要组成部分和亮点所在&#xff0c;可以完成包括普通查询、表达式查询、快捷查询、区间查询、组合查询在内的查询操作。where方法的参数支持字符串和数组&#xff0c;虽然也可以使用对象但并不建议。##…