两个相等的数据,经过排序后,排序算法保证其相对位置不发生变化,则称这个排序算法就有稳定性
判断方法:如果再比较的过程中没有发生跳跃式的交换(即非相邻的交换),那么就是稳定的
public static void insertSort(int[] array){
for (int i = 1; i < array.length; i++) {
int temp = array[i];
int j = i-1;
for (; j >= 0; j--) {
if(array[j] > temp){
//此处>=就不稳定了
array[j+1] = array[j];
}else{
array[j+1] = temp;
break;
}
}
if(j < 0){
array[0] = temp;
}
}
}
如果一组数据量比较小,越趋近于有序,用直接插入排序越快
希尔排序是对直接插入排序的优化
先分组进行预排序,即对每组进行直接插入排序,每组的数据量小,排序快
不断减少组数,进行预排序,进一步提高整体数据的有序性
直到最后为一组,进行直接插入排序
每分一次组,就进行一次直接插入排序;数据量不同,分组的方式也不同,必须保证最后一次只有一组
gap越大,步子越大,移动的越快,越无序
public static void shell(int[] array, int gap){
for (int i = gap; i < array.length; i++) {
int temp = array[i];
int j = i-gap;
for (; j >=0 ; j -= gap) {
if(array[j] > temp){
array[j+gap] = array[j];
}else{
array[j+gap] = temp;
break;
}
}
if(j < 0){
array[gap+j] = temp;
}
}
}
public static void shellSort(int[] array){
int gap = array.length;
while(gap > 1){
gap = gap/3+1;
// gap = gap/2;
shell(array,gap);
}
}
public void selectSort(int[] array){
for (int i = 0; i < array.length-1; i++) {
for (int j = i+1; j < array.length; j++) {
if(array[i] > array[j]){
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
}
}
public static void bullerSort(int[] array){
boolean flg = true;
for (int i = 0; i < array.length-1; i++) {
for (int j = 0; j < array.length-1-i; j++) {
if(array[j] > array[j+1]){
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
flg = false;
}
}
if(flg){
break;
}
}
}
//向下调整
//这里的end是结束区间的下标,注意不是长度len
public static void adjustDown(int[] array, int begin, int end){
int parent = begin;
int child = parent*2+1;
while(child <= end){
if(child+1 <= end && array[child+1] > array[child]){
child++;
}
if(array[parent] < array[child]){
int temp = array[parent];
array[parent] = array[child];
array[child] = temp;
}else{
break;
}
parent = child;
child = child*2+1;
}
}
//建立一个大堆
public static void creayHeap(int[] array){
int parent = (array.length-1-1)/2;
for (int i = parent; i >= 0; i--) {
adjustDown(array,i,array.length-1);
}
}
//堆排序
public static void heapSort(int[] array){
creayHeap(array);
int end = array.length-1;
while(end > 0){
int temp = array[0];
array[0] = array[end];
array[end] = temp;
end--;
adjustDown(array,0,end);
}
}
public static int Partition(int[] array, int low, int high){
int pivot = array[low];
while(low < high){
//注意这两个循环的顺序,先low后high,第一个坑没法填,最后一个数白白丧失
//注意一定是>= / <= ,而不是> <,如果< , > 相等的也交换,死循环
while(low < high && array[high] >= pivot){
high--;
}
array[low] = array[high];
while(low < high && array[low] <= pivot){
low++;
}
array[high] = array[low];
}
array[low] = pivot;
return low;
}
public static void Swap(int[] array, int i, int j){
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
public static int Hoare(int[] array, int low, int high){
int start = low;
int pivot = array[low];
while(low < high){
//注意顺序,先后再前,让high去找low,两者相遇的地方是比temp小的数
//同样的必须是>= <=,如果是>,< 会死循环的
while(low < high && array[high] >= pivot){
high--;
}
while(low < high && array[low] <= pivot){
low++;
}
Swap(array,low,high);
}
Swap(array,low,start);
return low;
}
public static void quickSort(int[] array, int start, int end){
if(start >= end){
return;
}
int pivot = Partition(array,start,end);
quickSort(array,start,pivot-1);
quickSort(array,pivot+1,end);
}
public static void quickSort(int[] array){
quickSort(array,0,array.length-1);
}
稳定性:不稳定
最坏情况时,可能会出现栈溢出的情况
所以可以通过基准值的选择进行优化
还是array[low] 作基准(pivot)
三数取中
array[mid] <= array[low] <= array[high]
可以确定其中最大/最小数的位置,在比较其余两个数
//元素交换
public static void Swap(int[] array, int i, int j){
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
//array[mid] <= array[low] <= array[high]
public static void ThreeMiddle(int[] array,int low, int high){
int mid = (low+high)/2;
if(array[low] < array[mid]){
Swap(array,low,mid);
}
if(array[high] < array[low]){
Swap(array,low,high);
}
if(array[low] < array[mid]){
Swap(array,low,mid);
}
//先确定mid的位置
if(array[mid] > array[start]){
swap(array,start,mid);
}
if(array[mid] > array[end]){
swap(array,mid,end);
}
//确定完成
if(array[start] > array[end]){
swap(array,start,end);
}
//先确定high的位置
if(array[mid] > array[high]){
Swap(array,mid,high);
}
if(array[low] > array[high]){
Swap(array,low,high);
}
//确定完成
if(array[mid] > array[low]){
Swap(array,mid,low);
}
}
public static void quickSort2(int[] array){
if(array.length == 0){
return;
}
Stack<Integer> stack = new Stack<>();
stack.push(0);
stack.push(array.length-1);
while(!stack.isEmpty()){
int high = stack.pop();
int low = stack.pop();
int pivot = Partition(array,low,high);
if(pivot > low+1) {
stack.push(low);
stack.push(pivot - 1);
}
if(pivot < high-1) {
stack.push(pivot + 1);
stack.push(high);
}
}
}
先将已有的序列分解成较短的子序列,使每个子序列有序,再将已经有序的子序列合并,得到完全有序的序列,即分解与合并
public static void merge(int[] array, int low, int mid, int high){
int[] temp = new int[high-low+1];
int k = 0;
int s1 = low;
int e1 = mid;
int s2 = mid+1;
int e2 = high;
while(s1 <= e1 && s2 <= e2){
while(s1 <= e1 && array[s1] <= array[s2]){
temp[k++] = array[s1++];
}
while(s2 <= e2 && array[s2] <= array[s1]){
temp[k++] = array[s2++];
}
}
while(s1 <= e1){
temp[k++] = array[s1++];
}
while(s2 <= e2){
temp[k++] = array[s2++];
}
for (int i = 0; i < temp.length; i++) {
array[i+low] = temp[i];
}
}
public static void mergeSort(int[] array, int low, int high){
if(low == high){
return;
}
int mid = (low+high)/2;
mergeSort(array,low,mid);
mergeSort(array,mid+1,high);
merge(array, low, mid, high);
}
public static void mergeSort(int[] array){
mergeSort(array,0,array.length-1);
}
public static void merge(int[] array, int gap){
int[] temp = new int[array.length];
int k = 0;
int s1 = 0;
int e1 = s1+gap-1;
int s2 = e1+1;
int e2 = s2+gap-1 > array.length-1 ? array.length-1 : s2+gap-1;
//有两段
while(s2 < array.length) {
while (s1 <= e1 && s2 <= e2) {
while (s1 <= e1 && array[s1] <= array[s2]) {
temp[k++] = array[s1++];
}
while (s2 <= e2 && array[s2] <= array[s1]) {
temp[k++] = array[s2++];
}
}
while(s1 <= e1) {
temp[k++] = array[s1++];
}
while(s2 <= e2){
temp[k++] = array[s2++];
}
s1 = e2+1;
e1 = s1+gap-1;
s2 = e1+1;
e2 = s2+gap-1 > array.length-1 ? array.length-1 : s2+gap-1;
}
//只有一段了
while(s1 < array.length && s1 <= e1){
temp[k++] = array[s1++];
}
for (int i = 0; i < temp.length; i++) {
array[i] = temp[i];
}
}
public static void mergeSort2(int[] array){
for (int gap = 1; gap < array.length; gap*=2) {
merge(array,gap);
}
}
long begin = System.currentTimeMillis();
insertSort(array);
long end = System.currentTimeMillis();
System.out.println(end - begin);
基数排序又叫“桶子排序”