目录
稳定的排序算法:排序后相同数值的元素位置不变。
插入排序
稳定的排序方法。
将一个数据插入到已经排好序的有序数组中,从而得到一个新的有序数组,算法适用于少量数据的排序。
public class InserSort extends Sort {
//从小到大排列
@Override
public void sort(int[] array) {
int length = array.length;
//从数组的第二个位置开始向前比较
for (int i = 1; i < length; i++) {
int temp = array[i];//待插入元素
int j = i-1;//已经排序好的数组最后一位
while (j>=0&&array[j]>temp){
//如果大于待插入元素,就将元素向后移动一位,此时位置j的元素待插入,继续比较
array[j+1] = array[j];
j--;
}
//跳出循环后,j的位置小于待插入元素
array[j+1] = temp;//将待插入元素插入到j+1的位置中
}
}
}
选择排序
不稳定的排序方法。
从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。
public class SelectSort extends Sort {
@Override
public void sort(int[] array) {
int length = array.length;
for (int i = 0; i < length; i++) {
int temp = array[i];
int index = i;
for (int j = i; j < length; j++) {
if(temp>array[j]){
temp = array[j];
index = j;
}
}
if(index!=i){
swap(array,i,index);
}
}
}
public void swap(int[] data, int i, int j){
int tmp=data[i];
data[i]=data[j];
data[j]=tmp;
}
}
快速排序
不稳定的算法
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序。
可以用数组第一个数作为基准进行比较
public class QuickSort extends Sort {
@Override
public void sort(int[] array) {
quickSort(array, 0, array.length - 1);
}
public void quickSort(int[] array, int start, int end) {
int pivotNum = array[start];
int low = start;
int hight = end;
while (low<hight){
while (low<hight&&array[hight]>=pivotNum){
hight--;
}
array[low] = array[hight];
while (low<hight&&array[low]<=pivotNum){
low++;
}
array[hight] = array[low];
}
array[low] = pivotNum;
if(low+1<end)quickSort(array,low+1,end);
if(low-1>start)quickSort(array,start,low-1);
}
}
冒泡排序
稳定的排序算法
让数组当中相邻的两个数进行比较,数组当中比较小(或比较大)的数值向下沉;外层for循环控制循环次数,内层for循环控制相邻的两个元素进行比较。直到没有相邻元素需要交换,排序完成。
public class BubbleSort extends Sort {
@Override
public void sort(int[] array) {
int length = array.length;
for (int i = 0; i < length; i++) {
for (int j = 0; j < length - 1 - i; j++) {
if(array[j]>array[j+1]){
swap(array,j,j+1);
}
}
}
}
public void swap(int[] data, int i, int j){
int tmp=data[i];
data[i]=data[j];
data[j]=tmp;
}
}
希尔排序
不稳定的排序算法
是插入排序的一种,又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。
把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的元素越来越多,当增量减至1时,所有元素被分成一组,排序终止。
初始增量可以为数组长度的1/2,每次再取1/2。
public class ShellSort extends Sort {
@Override
public void sort(int[] array) {
int length = array.length;
int d = length/2;
while (d>0){
for (int i = 0; i < d; i++) {
for (int j = i+d; j < length; j+=d) {
int num = array[j];
int k = j-d;
while (k>=0&&num < array[k]){
array[k+d] = array[k];
k-=d;
}
array[k+d] = num;
}
}
d/=2;
}
}
}
归并排序
稳定的排序方法
将已有序的子序列合并,得到完全有序的序列。
//归并排序:递归的将2个有序数组合并成一个。
public int[] mergeSort(int[] array, int low, int hight) {
//如果low == hight,则表示不能继续递归,直接返回元素
if(low==hight){
return new int[]{array[low]};
}
//找到中间下标
int mid = low+(hight-low)/2;
//对左右2边数组排序
int[] leftArr = mergeSort(array, low, mid);
int[] rightArr = mergeSort(array, mid + 1, hight);
//将2个有序数组合并成新的有序数组
int[] newArr = new int[leftArr.length+rightArr.length];
int i = 0;int j = 0;int k = 0;
while (i<leftArr.length&&j<rightArr.length){
newArr[k++] = leftArr[i]<rightArr[j]?leftArr[i++]:rightArr[j++];
}
while (i<leftArr.length){
newArr[k++] = leftArr[i++];
}
while (j<rightArr.length){
newArr[k++] = rightArr[j++];
}
return newArr;
}
基数排序
稳定的排序算法
将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。
先排好个位,然后排好各位的基础上排十位,以此类推,直到遍历最高位次,排序结束。
初始化10个桶(固定的),桶下标为0-9;
通过得到待排序数字的个、十、百等位的数字,把这个数字对应的元素放到对应的桶中;
基数排序有两种排序方式:LSD和MSD,最小位优先(从右边开始)和最大位优先(从左边开始);
LSD排序:
//d是数组元素的最大位数(几位数)
private void radixSort(int[] aar,int d){
int m = 1;
int n = 1;
int k = 0;
int length = aar.length;
int[][] temp = new int[10][length];
int[] orders = new int[10];
while (m<=d){
for (int i = 0; i < length; i++) {
int lsd = (aar[i]/n)%10;
temp[lsd][orders[lsd]] = aar[i];
orders[lsd]++;
}
for (int i = 0; i < 10; i++) {
if(orders[i]!=0){
for (int j = 0; j < orders[i]; j++) {
aar[k++] = temp[i][j];
}
orders[i] = 0;
}
}
k = 0;
n*=10;
m++;
}
}
堆排序
不稳定的排序算法
了解二叉树的概念:https://baike.baidu.com/item/%E4%BA%8C%E5%8F%89%E6%A0%91/1602879?fr=aladdin
堆:一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
在堆的数据结构中,堆中的最大值(大顶堆)或最小值(小顶堆)总是位于根节点。(取决于从小到大还是从大到小排序)
排序过程:将堆的末端子节点作调整,使得子节点永远大于或小于父节点;将根节点与最后一个节点交换,断开最后一个节点后,重新构建大顶推(或小顶推),递归排序。
public class HeapSort extends Sort {
@Override
public void sort(int[] array) {
System.out.println("开始排序");
int length= array.length;
//循环建堆
for(int i=0;i<length-1;i++){
//建堆
buildMaxHeap(array,length-1-i);
//交换堆顶和最后一个元素
swap(array,0,length-1-i);
System.out.println(Arrays.toString(array));
}
}
//对data数组从0到lastIndex建大顶堆,父节点:有叶子的节点,除根节点外也是叶子节点
private void buildMaxHeap(int[] array, int lastIndex) {
//从lastIndex处节点(最后一个节点)的父节点开始
for(int i=(lastIndex-1)/2;i>=0;i--){
//如果当前i节点的子节点存在
while(i*2+1<=lastIndex){
//i节点的左子节点的索引
int biggerIndex=2*i+1;
//如果biggerIndex小于lastIndex,即biggerIndex+1代表的i节点的右子节点存在
if(biggerIndex<lastIndex){
//若果右子节点的值较大
if(array[biggerIndex]<array[biggerIndex+1]){
//biggerIndex总是记录较大子节点的索引
biggerIndex++;
}
}
//如果i节点的值小于其较大的子节点的值
if(array[i]<array[biggerIndex]){
//交换他们
swap(array,i,biggerIndex);
//将biggerIndex赋予k,开始while循环的下一次循环,重新保证k节点的值大于其左右子节点的值
}else{
break;
}
}
}
}
public void swap(int[] data, int i, int j){
int tmp=data[i];
data[i]=data[j];
data[j]=tmp;
}
}