不要独享荣耀。独享荣耀,有天就会独吞苦果。
说到排序算法最先想到的就是冒泡排序了,它是最简单也是最慢的排序方法,双层for循环对每两项数值进行比较交换
/**
* 冒泡排序
* @param array
*/
public static void maoPao(int []array){
int temp;
for(int i=1;iarray[j+1]) {
temp=array[j];
array[j]=array[j+1];
array[j+1]=temp;
}
}
}
for(int i=0;i
循环遍历整个数组,不断把最小的值放到前面
/**
* 选择排序
* @param array
*/
public static void xuanZe(int []array) {
int index,temp;
for(int i=0;iarray[j]) {
index=j;//只对index值改变,不交换元素位置
}
}
if(i!=index) {
temp=array[index];
array[index]=array[i];
array[i]=temp;
}//一轮排序进行一次数组位置交换
System.out.print("第"+i+"次:");
}
for(int i=0;i
遍历整个数组,不断插入较小的数字到已排好顺序的部分中
/**
* 插入排序
* @param array
*/
public static void chaRu(int []array) {
int temp;
for(int i=1;i0 && temp < array[j-1]) {
array[j] = array[j-1];
j--;
}
array[j] = temp;
}
for(int i=0;i
采用分治的思想,先取中间值,分别从双端比较,把左端换成都比中间值小的,右端都比中间值大,然后重复此操作
/**
* 快速排序
* @param array
* @param left
* @param right
*/
public static void kuaiSu(int []array,int left,int right){
if(left < right) {
int i=left,j=right;
int pivot = array[left];//选择最左边的元素作为中间值
/**
* 分治
*/
while(i < j) {
while(i < j && array[j] >= pivot) {
j--;
}
if(i < j) {
array[i] = array[j];
i++;
}
while(i < j&& array[i] < pivot){
i++;
}
if(i < j) {
array [j] =array [i];
j--;
}
}
array [i]=pivot;
//递归
kuaiSu(array,left,i-1);
kuaiSu(array,i+1,right);
}
}
如果你看不懂这张图可以看看这个漫画坐在马桶上看算法
与直接插入一样,只是找合适的插入位置的方式不同,这里是按照二分法找到合适的位置,可以减少比较的次数
/**
* 二分查找插入排序
* @param a
*/
public static void erFenChaZhao(int[] a){
for(int i = 0;i < a.length;i++){
int temp = a[i];
int left = 0;
int right = i-1;
int mid = 0;
while(left <= right){
mid = (left+right)/2;
if(temp= left; j--){
a[j+1] = a[j];
}
if(left != i){
a[left] = temp;
}
}
}
希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。希尔排序是非稳定排序算法。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率;
但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。
先取一个正整数d1 < n, 把所有相隔d1的记录放一组,每个组内进行直接插入排序;然后d2 < d1,重复上述分组和排序操作;直至di = 1,即所有记录放进一个组中排序为止。
/**
* 希尔排序
* @param array
*/
/**
* 希尔排序的原理:根据需求,如果你想要结果从小到大排列,它会首先将数组进行分
组,然后将较小值移到前面,较大值
* 移到后面,最后将整个数组进行插入排序,这样比起一开始就用插入排序减少了数
据交换和移动的次数,
* 可以说希尔排序是加强 版的插入排序 拿数组5, 2,8, 9, 1, 3,4来说,数组长
度为7,当increment为3时,数组分为两个序列
* 5,2,8和9,1,3,4,第一次排序,9和5比较,1和2比较,3和8比较,4和比其
下标值小increment的数组值相比较
* 此例子是按照从小到大排列,所以小的会排在前面,第一次排序后数组为5, 1, 3,
4, 2, 8,9
* 第一次后increment的值变为3/2=1,此时对数组进行插入排序, 实现数组从大到
小排
*/
public static void xiEr(int[] array){
int d = array.length;
while(true){
d = d/2;
for(int x = 0;x=0;j--){
array[j+d]=array[j];
}
array[j+d] = temp;
}
}
if(d == 1){
break;
}
}
System.out.println(Arrays.toString(array));
}
堆排序是一种树形选择排序,是对直接选择排序的有效改进。
堆的定义下:具有n个元素的序列 (h1,h2,...,hn),当且仅当满足
(hi>=h2i,hi>=h2i+1)或(hi<=h2i,hi<=h2i+1) (i=1,2,...,n/2)时称之为堆。在这里
只讨论满足前者条件的堆。由堆的定义可以看出,堆顶元素(即第一个元素)必为
最大项(大顶堆)。完全二叉树可以很直观地表示堆的结构。堆顶为根,其它为左
子树、右子树。
思想:初始时把要排序的数的序列看作是一棵顺序存储的二叉树,调整它们的存储
序,使之成为一个 堆,这时堆的根节点的数最大。然后将根节点与堆的最后一个节
点交换。然后对前面(n-1)个数重新调整使之成为堆。依此类推,直到只有两个节点
的堆,并对 它们作交换,最后得到有n个节点的有序序列。从算法描述来看,堆排
序需要两个过程,一是建立堆,二是堆顶与堆的最后一个元素交换位置。所以堆排
序有两个函数组成。一是建堆的渗透函数,二是反复调用渗透函数实现排序的函
数。
/**
* 堆排序
* @param array
*/
public static void HeapSort(int[] array){
for(int i=0;i=0;i--){
//k保存正在判断的节点
int k = i;
//如果k节点的子节点存在
while(k*2+1<=lastIndex){
//将k点左子节点的索引赋值给biggerIndex
int biggerIndex = 2*k+1;
//如果biggerIndex小于lastIndex,代表k节点的右子节点存在
if(biggerIndex < lastIndex){
//如果右子节点的值较大
if(data[biggerIndex]
归并排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
/**
* 归并排序
* @param array
*/
public static void mergingSort(int[] array) {
sort(array, 0, array.length - 1);
System.out.println(Arrays.toString(array) + " mergingSort");
}
private static void sort(int[] data, int left, int right) {
if (left < right) {
//找出中间索引
int center = (left + right) / 2;
//对左边数组进行递归
sort(data, left, center);
//对右边数组进行递归
sort(data, center + 1, right);
//合并
merge(data, left, center, right);
}
}
private static void merge(int[] data, int left, int center, int right) {
int[] tmpArr = new int[data.length];
int mid = center + 1;
//third记录中间数组的索引
int third = left;
int tmp = left;
while (left <= center && mid <= right) {
//从两个数组中取出最小的放入中间数组
if (data[left] <= data[mid]) {
tmpArr[third++] = data[left++];
} else {
tmpArr[third++] = data[mid++];
}
}
//剩余部分依次放入中间数组
while (mid <= right) {
tmpArr[third++] = data[mid++];
}
while (left <= center) {
tmpArr[third++] = data[left++];
}
//将中间数组中的内容复制回原数组
while (tmp <= right) {
data[tmp] = tmpArr[tmp++];
}
}
将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。
/**
* 基数排序
* @param array
*/
public static void radixSort(int[] array) {
//首先确定排序的趟数;
int max = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] > max) {
max = array[i];
}
}
int time = 0;
//判断位数;
while (max > 0) {
max /= 10;
time++;
}
//建立10个队列;
ArrayList> queue = new ArrayList<>();
for (int i = 0; i < 10; i++) {
ArrayList queue1 = new ArrayList<>();
queue.add(queue1);
}
//进行time次分配和收集;
for (int i = 0; i < time; i++) {
//分配数组元素;
for (int anArray : array) {
//得到数字的第time+1位数;
int x = anArray % (int) Math.pow(10, i + 1) / (int) Math.pow(10, i);
ArrayList queue2 = queue.get(x);
queue2.add(anArray);
queue.set(x, queue2);
}
int count = 0;//元素计数器;
//收集队列元素;
for (int k = 0; k < 10; k++) {
while (queue.get(k).size() > 0) {
ArrayList queue3 = queue.get(k);
array[count] = queue3.get(0);
queue3.remove(0);
count++;
}
}
}
System.out.println(Arrays.toString(array) + " radixSort");
}