图片来自网络
一、用泛型实现快排,可以传入不通类型进行排序,比如String数组,Integer数组。
/*** 快速排序
*
*@authorchx
**/
public classQuickSort {/*** 数组内数值的交换函数
*
*@paramarr
* 原数组
*@paramleftIndex
* 左索引
*@paramrightIndex
* 右索引*/
private static void change(T[] arr, int leftIndex, intrightIndex) {
T temp=arr[leftIndex];
arr[leftIndex]=arr[rightIndex];
arr[rightIndex]=temp;
}public static void sort(T[] arr, int left, intright) {if (right
return;
}
T flag= arr[left];//哨兵的值
int indexLeft = left;//本轮查找需要的左索引
int indexRight = right;//本轮查找需要的右索引
while (indexLeft !=indexRight) {//开始从右向左找,找比哨兵小的值。或者直到遇到左索引
while (Integer.parseInt(arr[indexRight].toString()) >=Integer.parseInt(flag.toString())&& indexLeft
indexRight--;
}//从左向右找,找到比哨兵大的值,或者直到遇到右索引
while (Integer.parseInt(arr[indexLeft].toString()) <=Integer.parseInt(flag.toString())&& indexLeft
indexLeft++;
}if (indexLeft
change(arr, indexLeft, indexRight);
}
}//此时一遍探索结束,将哨兵和当前的值进行交换,并进行分区探索
change(arr, left, indexLeft);//右边探索
sort(arr, indexRight + 1, right);//左边探索
sort(arr, left, indexLeft - 1);
}
}
二、利用Arrays.sort()进行排序
突然有个同学咨询Arrays.sort用法,正好在此记录。
1.简介:有的时候不愿意去写排序程序,可以利用java自带的Arrays.sort()方法。
2.使用规则:总结为,基本数据类型直接放,引用数据类型需要利用实现了Comparator的对象辅助排序。
3.具体用法:
packagemianshi;importjava.util.Arrays;importjava.util.Comparator;public class SortTest implements Comparator{private intsortValue;public intgetSortValue() {returnsortValue;
}public void setSortValue(intsortValue) {this.sortValue =sortValue;
}public static voidmain(String[] args) {
SortTest[] list= new SortTest[5];for (int i = 0; i < list.length; i++) {
list[i]= newSortTest();
list[i].setSortValue(i*2);
}
Comparator cmp = newSortTest();
Arrays.sort(list, cmp);for (int i = 0; i < list.length; i++) {
System.out.print(list[i].getSortValue()+ " ");
}
}
@Overridepublic intcompare(SortTest o1, SortTest o2) {if (o1.getSortValue() >o2.getSortValue()) {return -1;
}else if(o1.getSortValue()
}return 0;
}
}
返回值规则:compare是实现对比的方法,正数-大于,0-等于,负数-小于。所以本程序是倒序排序。
tips:感兴趣的可以百度下compare的实现原理、算法选择。有很多需要了解的内容。
三、有关排序算法
//选择排序
public static void xuanZeSort(int[] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] >arr[j]) {
int tmp =arr[i];
arr[i] =arr[j];
arr[j] =tmp;
}
}
}
}
/**
* 插入排序
*
* @param
* @param arr
* @return
* @author chx
* @date 2020/6/5 17:48
*/
public static void insertSort(int[] arr) {
//就一个核心思想。从第I个数开始向左找比其大(小)的位置index,期间全体右移。
for (int i = 1; i < arr.length; i++) {
int flag =arr[i];
int j =i;
while (j > 0 && flag < arr[j - 1]) {
arr[j] = arr[j - 1];
j--;
}
//此位置要么为0要么为找到的位置,由于一直右移,所以一定替换。
arr[j] =flag;
}
}
/**
* 希尔排序:真的只是对插入排序做了改善,代码及其相似。
*
* @param arr
*/
public static void shellSort(int[] arr) {
//增量因子这里可以百度,因子的选择有一定可能会影响效率。
int step = arr.length / 3 + 1;
//和插入排序多了一个while循环,当步长为0时表示排序完成。
while (step > 0) {
//从[步长位]开始,和所有第[i-步长]及[j-步长]比较,并进行移位。
for (int i = step; i < arr.length; i++) {
int flag =arr[i];
int j = i -step;
//和所有[j-step]位数值进行比较,
while (j >= 0 && flag
//移位
arr[j + step] =arr[j];
j -=step;
}
arr[j + step] =flag;
}
step = (int) Math.floor(step / 3);
}
}
/**
* 堆排序-大顶堆排序(升序)
*
* @param
* @param arr
* @return
* @author chx
* @date 2020/6/8 11:18
*/
private static void bigHeapSort(int[] arr) {
//将树的结构线性化,按照左子节点坐标=2*i+1,右子节点坐标=2*i+2。其中i表示坐标。
//所以从最后一个非叶子节点开始(坐标为最大下标/2),自左向右(自右向左)比较其叶子节点和其父节点大小。
//确保父节点永远比叶子节点大(小顶堆找最小),最终构建好的线性表即为大顶堆(其根节点是最大值)。其根节点要么最大要么最小。
for (int i = arr.length / 2; i >= 0; i--) {
changeHeapValue(arr, i, arr.length);
}
//创建完堆之后,对堆进行调整,每次调整把最大值放于根节点,并调换最后一个叶子节点和根节点,直到堆里只剩一个数据。
int length =arr.length;
for (int i = length - 1; i > 0; i--) {
//交换根节点和最后一个子节点,这样就相当于把最大值取出来了。
swap(arr, 0, i);
//由于换了根节点和最后一个节点,所以重新排序。
length--;
changeHeapValue(arr, 0, length);
}
}
/**
* 交换两个下标的数值
*
* @param
* @param arr 数组
* @param index 下标A
* @param swapIndex 下标B
* @return
* @author chx
* @date 2020/6/8 11:41
*/
private static void swap(int[] arr, int index, intswapIndex) {
int tmp =arr[index];
arr[index] =arr[swapIndex];
arr[swapIndex] =tmp;
}
/**
* 创建大顶堆过程中,比较父节点及其叶子节点的大小,进行改值操作。
*
* @param arr
* @param index
* @return
* @author chx
* @date 2020/6/8 12:07
*/
private static void changeHeapValue(int[] arr, int index, intlenth) {
int leftIndex = index * 2 + 1;
int rightIndex = index * 2 + 2;
int tmpIndex =index;
//此处不用arr.length的原因是,后面对堆进行排序时会修改长度。因为最终堆只剩一个的时候就排序完了。
if (leftIndex < lenth && arr[tmpIndex]
//左子节点大于其父节点,记录,后面要交换。
tmpIndex =leftIndex;
}
if (rightIndex < lenth && arr[tmpIndex]
//右子节点大于其父节点,记录,后面进行交换。
tmpIndex =rightIndex;
}
if (tmpIndex !=index) {
// 期间有改动,说明找到需要交换的值了,进行交换。
swap(arr, index, tmpIndex);
// 此子节点下继续探索,防止由于子父节点更换,导致原来子节点及其子节点的子节点 排列好的数据已经不符合大顶堆规则。
changeHeapValue(arr, tmpIndex, lenth);
}
}
/**
* 归并排序之递归实现
*/
public static void mergeSortRecurrence(int[] arr, int left, intright) {
//最小单位是两两比较,所以遇到1以下的就直接返回。
if (left
int mid = (left + right) / 2;
//左边分割
mergeSortRecurrence(arr, left, mid);
//右边分割
mergeSortRecurrence(arr, mid + 1, right);
//合并排序
mergeSortMerge(arr, left, mid, right);
}
}
/**
* 合并分割后的数组,并排序。最终会合为一个排序好的大数组。
*
* @param arr
* @param left
* @param mid
* @param right
*/
private static void mergeSortMerge(int[] arr, int left, int mid, intright) {
//创建一个临时数组,用左数组的值与右数组的比较,由于左右两边都是有序的,所以才能保证放进临时数组的都是正确的。
int[] tmp = new int[arr.length];//辅助数组
int p1 = left, p2 = mid + 1, k = left;//p1、p2是检测指针,k是存放指针
while (p1 <= mid && p2 <=right) {
if (arr[p1] <=arr[p2]){
tmp[k++] = arr[p1++];
}
else{
tmp[k++] = arr[p2++];
}
}
while (p1 <= mid) tmp[k++] = arr[p1++];//如果左边未检测完,直接将后面所有元素加到合并的序列中
while (p2 <= right) tmp[k++] = arr[p2++];//同上
//复制回原素组
for (int i = left; i <= right; i++) {
arr[i] =tmp[i];
}
}