常用排序算法--java版
package com.whw.sortPractice; import java.util.Arrays; public class Sort
{
/**
* 遍历一个数组
* @param sortArray
*/
public void outputArray(int[] sortArray)
{
for(int i = 0;i < sortArray.length;i++)
{
System.out.print(sortArray[i] + " ");
}
System.out.println();
} // **********************************插入排序********************************** /**
* 插入排序
* 排序的基本思想是把待排元素前面的元素当做是一个有序列表 把待排元素后面的元素当做一个无序列表
* 只要把待排元素插入到前面的有序列表中某个位置即可
* 待排元素从数组中的第二个数开始到数组中的最后一个数结束
*
* 插入排序的效率非常低 因为一次只能将数据移动一位
* @param sortArray
*/
public void insertSort(int[] sortArray)
{
// 这里的i记录的是对数组中的第几个元素进行排序
for(int i = 1;i < sortArray.length;i++)
{
// 把待排元素放到临时变量里面
int tem = sortArray[i];
// j保存的是待排元素最后去的位置的前一个位置
int j = 0;
for(j = i - 1;(j >= 0) && (sortArray[j] > tem);j--)
{
sortArray[j+1] = sortArray[j];
}
sortArray[j+1] = tem;
}
// 输出结果
outputArray(sortArray);
} /**
* shell排序是快速排序的改良版
* shell排序先将要排序的序列切割成多个组 然后在每个组内再使用插入排序
* @param sortArray 待排序的数组
*/
public void shellSort(int[] sortArray)
{
// 用这个数组里面的数去依次切割待排序的数组
int[] increArray = new int[]{5,4,3,2};
// 使用增量数组里面的增量依次排序
for(int i = 0;i < increArray.length;i++)
{
// 使用每一个增量进行插入排序 循环一开始 j就定位到了子数组中的第二个元素
for(int j = i + increArray[i];j < sortArray.length;j += increArray[i])
{
// 保存待排序元素的临时变量
int tem = sortArray[j];
int k = j - increArray[i];
for(k = j - increArray[i];(k >= 0) && (sortArray[k] > tem);k -= increArray[i])
{
sortArray[k + increArray[i]] = sortArray[k];
}
k += increArray[i];
sortArray[k] = tem;
}
System.out.println("第" + (i+1) + "趟排序完成 开始遍历数组元素");
outputArray(sortArray);
}
System.out.println("shell排序完成,开始插入排序");
insertSort(sortArray);
} // *************************************选择排序******************************* /**
* 选择排序的基本思想是 每次都选择出从第i到最后一个元素中最小(大)的那一个与第i个元素交换位置
* @param sortArray
*/
public void selectSort(int[] sortArray)
{
// 外层循环n-1次
for(int i = 0;i < sortArray.length - 1;i++)
{
// 找出第i个到最后的元素中最小的那个元素
// 最小的元素
int min = sortArray[i];
// 最小元素出现的位置
int pos = i;
for(int j = i;j < sortArray.length;j++)
{
if(sortArray[j] < min)
{
min = sortArray[j];
pos = j;
}
}
if(i != pos)
{
// 把最小元素和第i个元素交换位置
sortArray[pos] = sortArray[i];
sortArray[i] = min;
}
}
} /**
* 二元选择排序 每趟排序中选出最大值和最小值 然后分别把这个最大值和最小值放到参与排序的元素的最左端和最右端
* 总共循环[n/2](下取整)次
* @param sortArray
*/
public void twoEleSelectSort(int[] sortArray)
{
// 循环次数
int cycleTime = sortArray.length / 2;
for(int i = 0;i < cycleTime;i++)
{
// 记录最大最小数以及他们出现的位置
int min = sortArray[i];
int minPos = i;
int max = sortArray[i];
int maxPos = i;
// 找出待排元素的最大值和最小值
for(int j = i;j < sortArray.length - i;j++)
{
if(sortArray[j] < min)
{
min = sortArray[j];
minPos = j;
}
if(sortArray[j] > max)
{
max = sortArray[j];
maxPos = j;
}
}
// 把最大值和最小值分别放到待排元素的最左端和最右端
sortArray[minPos] = sortArray[i];
sortArray[i] = min;
sortArray[maxPos] = sortArray[sortArray.length - i - 1];
sortArray[sortArray.length - i - 1] = max;
}
} /**
* 堆排序 可以把一个数组逻辑化成一棵二叉堆 父节点的值大于任一子节点的值时是大根堆 父节点的值小于任一子节点的值是小根堆
* 大根堆的根节点就是当前数组中最大的元素 然后把这个最大的元素和待排元素中最后一个元素交换位置即可
* 排序的过程就是 建树->交换 这个过程循环往复
* 相当于每次通过建树的方式找出待排元素中最大值的那个元素
* @param sortArray
*/
/**
* @param sortArray
*/
public void heapSort(int[] sortArray)
{
// 建树 父节点和子节点元素数组下标之间的关系为 父节点的下标是i 左子节点的下标是2*i+1 右子节点的下标是2*i+2
// 建树的基本思路是 从最后一个父节点开始保证每个父节点要比左右孩子节点的值大
// 所以要找到最后一个父节点然后不停的和左右孩子节点进行比较和交换
// 通过这样不停的比较和交换最终能保证 sortArray[0]一定是数组元素中的最大值 // 最外层的循环指定了要对哪些元素进行建树
int arrLength = sortArray.length;
for(int i = arrLength - 1; i >= 0;i--)
{
// 建树 从给定元素的最后一个开始
for(int j = i; j >= 0;j--)
{
// 判断左子节点是否存在
if(2 * j + 1 >= arrLength || 2 * j + 1 > i)
{
continue;
}
// 如果比左子节点要小就要和左子节点交换
if(sortArray[j] < sortArray[2*j+1])
{
int tem = 0;
tem = sortArray[j];
sortArray[j] = sortArray[2*j+1];
sortArray[2*j+1] = tem;
}
// 判断右子节点是否存在
if(2 * j + 2 >= arrLength || 2 * j + 2 > i)
{
continue;
}
// 如果比右子节点要小就要和右子节点交换
if(sortArray[j] < sortArray[2*j+2])
{
int tem = 0;
tem = sortArray[j];
sortArray[j] = sortArray[2*j+2];
sortArray[2*j+2] = tem;
}
}
// 建树完成 这个时候的sortArray[0]就是待排元素中值最大的那个
int tem = 0;
tem = sortArray[0];
sortArray[0] = sortArray[i];
sortArray[i] = tem;
outputArray(sortArray);
}
} // ****************************************交换排序**************************** /**
* 冒泡排序 每次都从数组中的第一个元素开始 每次都把待排元素中的最大的那个沉到最后一个
* 每次比较相邻的两个元素 如果后面的比前面的小就交换
* @param sortArray
*/
public void bubbleSort(int[] sortArray)
{
// 外层循环控制待排元素的终点
int endPostion = sortArray.length - 1;
for(int i = endPostion;i >= 0;i--)
{
// 挨个比较待排元素中相邻的元素
for(int j = 0;j < i;j++)
{
if(sortArray[j] > sortArray[j+1])
{
int tem = 0;
tem = sortArray[j];
sortArray[j] = sortArray[j+1];
sortArray[j+1] = tem;
}
}
}
} /**
* 冒泡算法改进版
* 在每一趟排序中增加一个boolean类型的变量 标识这一趟排序中是否有交换发生 如果没有交换发生说明数组已经是有序的
* @param sortArray
*/
public void bubbleSortAdvanced(int[] sortArray)
{
// 外层循环控制待排元素的终点
int endPosition = sortArray.length - 1;
boolean isChange = true;
for(int i = endPosition;i >= 0;i--)
{
if(isChange == false)
{
return;
}
isChange = false;
for(int j = 0;j < i;j++)
{
if(sortArray[j] > sortArray[j+1])
{
int tem = sortArray[j];
sortArray[j] = sortArray[j+1];
sortArray[j+1] = tem;
// 修改交换标识符
isChange = true;
}
}
}
} /**
* 双元素冒泡排序算法 每一趟排序中都把最大的元素沉到待排元素的最右端 把最小元素沉到待排元素的最左端
* @param sortArray
*/
public void twoElementBubbleSort(int[] sortArray)
{
// 外层循环控制待排元素的终点
int endPosition = sortArray.length - 1;
boolean isChange = true;
for(int i = endPosition;i >= 0;i--)
{
if(isChange == false)
{
return;
}
isChange = false;
// 把最大的元素沉下去
for(int j = 0;j < i;j++)
{
if(sortArray[j] > sortArray[j+1])
{
int tem = sortArray[j];
sortArray[j] = sortArray[j+1];
sortArray[j+1] = tem;
// 修改交换标识符
isChange = true;
}
}
// 把最小的元素浮上来
for(int j = i;j > 0;j--)
{
if(sortArray[j] < sortArray[j-1])
{
int tem = sortArray[j - 1];
sortArray[j - 1] = sortArray[j];
sortArray[j] = tem;
isChange = true;
}
}
}
} /**
* 快速排序 快速排序的规则如下
* 1、设置两个变量i、j初始化的时候i= j=sortArray.length-1 也就是说这两个指针初始化的时候一个指向第一个待排元素 一个指向最后一个待排元素
* 2、每次把待排元素的第一个当做关键数据赋值给key 即key=sortArray[0]
* 3、j向前移动 找到第一个比key小的元素sortArray[j] 让sortArray[j]和sortArray[i]交换
* 4、i向后移动 找到第一个比key大的元素sortArray[i] 让sortArray[i]和sortArray[j]交换
* 5、重复3到4 直到i和j相等
* 注意:快速排序中需要注意的地方有两个
* 1、只有sortArray[i]小于等于key的时候i才向前移动 或 sortArray[j]大于等于key的时候j才向后移动
* 2、根据注意的第一点 如果sortArray[i]和sortArray[j]交换 i j 这两个指针都不移动
*
* 经过一趟排序之后数组就变成了key左边的元素都不大于key key右边的元素都不小于key
* 只要对key左右两侧的子数组进行递归排序即可
* @param sortArray
*/
public void quickSort(int[] sortArray,int startIndex,int endIndex)
{
// 递归终止条件
if(startIndex >= endIndex)
{
return;
}
// 第一趟排序
int i = startIndex;
int j = endIndex;
int key = sortArray[i];
// 当两个指针没有相遇的时候循环要一直持续
// 这个循环结束的时候i和j已经相等
outer:while(i < j)
{
System.out.println(key);
// sortArray[j]比key要大指针就一直向前移动
while(sortArray[j] >= key)
{
System.out.println(sortArray[j] + " " + key);
j--;
// 这里也是一个需要注意的地方 如果j和i已经相等了就要结束外层循环
if(i == j)
{
break outer;
} }
if(i < j)
// sortArray[j]小于key的时候交换sortArray[i]和sortArray[j]
System.out.println("右侧交换" + sortArray[i] + " " + sortArray[j]);
int tem = sortArray[i];
sortArray[i] = sortArray[j];
sortArray[j] = tem;
outputArray(sortArray);
System.out.println("右侧交换完成");
// sortArray[i]比key要小指针就一直向后移动
while(sortArray[i] <= key && j > i)
{
i++;
if(i == j)
{
break outer;
}
}
// sortArray[i]大于key的时候交换sortArray[i]和sortArray[j]
System.out.println("左侧交换" + sortArray[i] + " " + sortArray[j]);
tem = sortArray[i];
sortArray[i] = sortArray[j];
sortArray[j] = tem;
outputArray(sortArray);
System.out.println("左侧交换完成");
}
outputArray(sortArray);
System.out.println("一次排序结束");
// 递归key左边的部分
quickSort(sortArray, startIndex, i-1);
// 递归key右边的部分
quickSort(sortArray, i+1,endIndex);
} /**
* 归并排序
* 归并排序的思路不算复杂 主要是递归 合并
* 先把待排数组从中间分开然后对左右两个子数组进行递归 直到子数组被划分为只有两个元素 对这两个元素进行递归之后然后合并 在这个合并的过程中两个元素发生了交换
* 首先要理解递归的过程 其次要理解合并
* 现在对这个算法还不是很理解
* @param sortArray
*/
public void mergeSort(int[] sortArray,int low,int high)
{
// 这一步就是在不停的拆分数组
int mid = (low + high) / 2;
if(low < high)
{
// 通过左右两侧的递归就能保证左右两侧的子数组全部有序
// 递归执行左边的部分
mergeSort(sortArray, low, mid);
// 递归执行右边的部分
mergeSort(sortArray, mid + 1, high); System.out.println("左右递归完成 测试左右数组是否有序");
for(int i = low;i <= mid;i++)
{
System.out.print(sortArray[i] + " ");
}
System.out.print("--------");
for(int i = mid+1;i <= high;i++)
{
System.out.print(sortArray[i] + " ");
}
System.out.println(); // 左右数组已经有序 可以进行交换
// 先把sortArray中的元素放到tem中 然后把tem中的元素赋值给sortArray中
// 这里的数组长度开辟出错 调了很长时间才调出来
int[] tem = new int[high - low + 1];
// 分别指向左右两侧数组第一个元素的指针
int leftIndex = low;
int rightIndex = mid + 1;
// 标识tem的指针
int temIndex = 0;
while(leftIndex <= mid && rightIndex <= high)
{
if(sortArray[leftIndex] < sortArray[rightIndex])
{
tem[temIndex] = sortArray[leftIndex];
leftIndex++;
}
else
{
tem[temIndex] = sortArray[rightIndex];
rightIndex++;
}
temIndex++;
}
System.out.println("全部移出");
System.out.println("tem[]中的元素为" + Arrays.toString(tem));
outputArray(sortArray); while(leftIndex <= mid)
{
tem[temIndex] = sortArray[leftIndex];
leftIndex++;
temIndex++;
} while(rightIndex <= high)
{
tem[temIndex] = sortArray[rightIndex];
rightIndex++;
temIndex++;
} for(int i = 0;i < tem.length;i++)
{
sortArray[low+i] = tem[i];
}
// 把tem中的前temIndex-1个移动到sortArray中 从low开始向后temIndex-1个位置上面去
/*int temIndex2 = 0;
int sortIndex = low;
while(temIndex2 <= temIndex-1)
{
sortArray[sortIndex] = tem[temIndex2];
temIndex2++;
sortIndex++;
}*/
System.out.println("重新移入");
outputArray(sortArray);
}
} public static void main(String[] args)
{
// 测试数组 {9,8,7,5,1,2,3,12,3,5,88,99,78,90,78,66,543,77,54,9,3,21,125}
int[] sortArray = new int[] {9,8,7,5,1,2,3,12,3,5,88,99,78,90,78,66,543,77,54,9,3,21,125};
Sort test = new Sort();
// test.insertSort(sortArray);
// test.shellSort(sortArray);
// test.selectSort(sortArray);
// test.twoEleSelectSort(sortArray);
// test.heapSort(sortArray);
// test.bubbleSort(sortArray);
// test.bubbleSortAdvanced(sortArray);
// test.twoElementBubbleSort(sortArray);
// test.quickSort(sortArray, 0, sortArray.length-1);
test.mergeSort(sortArray, 0, sortArray.length-1);
test.outputArray(sortArray);
}
}
常用排序算法--java版的更多相关文章
- 常用排序算法java实现
写在前面:纸上得来终觉浅.基本排序算法的思想,可能很多人都说的头头是到,但能说和能写出来,真的还是有很大区别的. 今天整理了一下各种常用排序算法,当然还不全,后面会继续补充.代码中可能有累赘或错误的地 ...
- 排序算法Java版,以及各自的复杂度,以及由堆排序产生的top K问题
常用的排序算法包括: 冒泡排序:每次在无序队列里将相邻两个数依次进行比较,将小数调换到前面, 逐次比较,直至将最大的数移到最后.最将剩下的N-1个数继续比较,将次大数移至倒数第二.依此规律,直至比较结 ...
- 排序算法系列:选择排序算法JAVA版(靠谱、清晰、真实、可用、不罗嗦版)
在网上搜索算法的博客,发现一个比较悲剧的现象非常普遍: 原理讲不清,混乱 啰嗦 图和文对不上 不可用,甚至代码还出错 我总结一个清晰不罗嗦版: 原理: 从数组头元素索引i开始,寻找后面最小的值(比i位 ...
- 排序算法Java版
选择排序: public static void selectSort(int[]a) { int minIndex=0; int temp=0; if((a==null)||(a.length==0 ...
- 我们一起来排序——使用Java语言优雅地实现常用排序算法
破阵子·春景 燕子来时新社,梨花落后清明. 池上碧苔三四点,叶底黄鹂一两声.日长飞絮轻. 巧笑同桌伙伴,上学径里逢迎. 疑怪昨宵春梦好,元是今朝Offer拿.笑从双脸生. 排序算法--最基础的算法,互 ...
- Java常用排序算法+程序员必须掌握的8大排序算法+二分法查找法
Java 常用排序算法/程序员必须掌握的 8大排序算法 本文由网络资料整理转载而来,如有问题,欢迎指正! 分类: 1)插入排序(直接插入排序.希尔排序) 2)交换排序(冒泡排序.快速排序) 3)选择排 ...
- Java 常用排序算法/程序员必须掌握的 8大排序算法
Java 常用排序算法/程序员必须掌握的 8大排序算法 分类: 1)插入排序(直接插入排序.希尔排序) 2)交换排序(冒泡排序.快速排序) 3)选择排序(直接选择排序.堆排序) 4)归并排序 5)分配 ...
- Java常用排序算法及性能测试集合
测试报告: Array length: 20000 bubbleSort : 573 ms bubbleSortAdvanced : 596 ms bubbleSortAdvanced2 : 583 ...
- 常用排序算法的总结以及编码(Java实现)
常用排序算法的总结以及编码(Java实现) 本篇主要是总结了常用算法的思路以及相应的编码实现,供复习的时候使用.如果需要深入进行学习,可以使用以下两个网站: GeeksForGeeks网站用于学习相应 ...
随机推荐
- nginx 同一域名下分目录配置显示php,html,资源文件
安装上nginx后 注意后nginx.conf 中的这么几行 error_log /var/log/nginx/error.log; 日志,这个很有用 include /etc/nginx/conf ...
- 用for循环求1-100的所有数的和
2.求1-100的所有数的和 x=0for y in range (1,101): x=x+yprint(x)#Python for循环中可以循环一个列表或者某一个字符串下面是for的基本格式,英文是 ...
- Go Web 问题集-持续更新
前端: 导入静态js,css报错,在确保js和css语法编写正确的前提下 GET 错误: 等问题 1.在服务器中运行:静态服务文件路径设置错误 2.本地运行:相对路径设置错误 3 ...
- 001-快速排序(C++实现)
快速排序的基本实现 快速排序算法是一种基于交换的高效的排序算法,它采用了分治法的思想: 1.从数列中取出一个数作为基准数(枢轴,pivot). 2.将数组进行划分(partition),将比基准数大的 ...
- C# WebBrowser的DrawToBitmap方法 截取网页保存为图片
bool mark = true; private void btnOpen_Click(object sender, EventArgs e) { ...
- 成都优步uber司机第一组与第二组的区别
成都优步uber司机被分成了两组,两组的奖励方式不相同,下面我们先来看看官方给出的奖励方式: 滴滴快车单单2.5倍,注册地址:http://www.udache.com/如何注册Uber司机(全国版最 ...
- 北京Uber优步司机奖励政策(4月6日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- 天津市人民优步Uber司机奖励政策(8.31-9.6)
"*结算周期为周一凌晨4点至下周一凌晨4点 滴滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单 ...
- Mysql 8.0.* zip版本 windows安装
一,MySQL8.0.*zip版本安装步骤. 1,下载 https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.15-winx64.zip 注现 ...
- Spring的cache缓存介绍
从3.1开始,Spring引入了对Cache的支持.其使用方法和原理都类似于Spring对事务管理的支持.Spring Cache是作用在方法上的,其核心思想是这样的:当我们在调用一个缓存方法时会把该 ...