目录
一.普通排序法
1.冒泡排序(交换排序)
在无序区间,通过相邻数的比较,将最大的数冒泡到无序区间的最后,持续这个过程,直到数组整体有序
时间复杂度:O(n^2) ,具有稳定性。
动态效果:排序(冒泡排序,选择排序,插入排序,归并排序,快速排序,计数排序,基数排序) - VisuAlgo
代码如下:
public class BubbleSort {
// 具有稳定性 时间复杂度O(n^2)
public void Sort(int[] array){
for (int i = 0; i < array.length-1; i++) { //元素n个 ,就循环n-1个 选择
boolean sorted = true;
for (int j = 0; j < array.length-i-1; j++) { // 排序
if(array[j]>array[j+1]){
swap(array,j,j+1);
sorted = false;
}
}
if(sorted){
return;
}
}
}
private void swap(int[] array, int j, int i) {
int e = array[i];
array[i] =array[j];
array[j] = e;
}
2.直接插入排序
整个区间被分为
1. 有序区间
2. 无序区间
每次选择无序区间的第一个元素,在有序区间内选择合适的位置插入.(具备稳定性 ,时间复杂度:O(n^2)-> 平均)
代码如下:
public class InsertSort {
public void Sort(int[] array){
for (int i = 0; i < array.length-1; i++) {
int e = array[i+1];
int j ;
for(j =i;j>=0 && array[j]> e;j--){
array[j+1] =array[j];
}
array[j] = e;
}
}
}
3.选择排序
每一次从无序区间选出最大(或最小)的一个元素,存放在无序区间的最后(或最前),直到全部待排 序的数据元素排完 。
时间复杂度:O(n^2) , 不具备稳定性。
代码如下:
public void selectSort(long[] array) {
for (int i = 0; i < array.length - 1; i++) {
int maxIdx = 0;
for (int j = 1; j < array.length - i; j++) {
if (array[j] > array[maxIdx]) {
maxIdx = j;
}
}
if (maxIdx != array.length - i - 1) {
swap(array, maxIdx, array.length - i - 1);
}
}
}
private void swap(int[] array, int j, int i) {
int e = array[i];
array[i] =array[j];
array[j] = e;
}
二.较为高级的排序法
1.希尔排序(属于插入排序)
时间复杂度:O(n*1.3) ,不具备稳定性。
原理:
希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数(n),把待排序文件中所有记录分成个组,所有距离为 n 的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和 排序的工作。当到达=1
时,所有记录在统一组内排好序。
1.
希尔排序是对直接插入排序的优化。
2.
当
gap > 1
时都是预排序,目的是让数组更接近于有序。当
gap == 1
时,数组已经接近有序的了, 这样就会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。
public void shellSort(long[] array) {
for (int g = array.length / 2; g > 1; g = g / 2) {
insertSortWithGap(array, g);
}
insertSortWithGap(array, 1);
}
private void insertSortWithGap(long[] array, int g) {
for (int i = 0; i < array.length - g; i++) {
long key = array[i + g];
int j;
for (j = i; j >= 0 && array[j] > key; j = j - g) {
array[j + g] = array[j];
}
array[j + g] = key;
}
}
2.归并排序
原理 :合并两个有序数组
时间复杂度:O(n* log(n)) , 具备稳定性。
代码如下:
private void RangeSort(long[] array, int from, int to) {
int size = to - from;
if (size <= 1) {
return;
}
int mid = from + (size / 2);
sortRange(array, from, mid);
sortRange(array, mid, to);
merge(array, from, mid, to);
}
private void merge(long[] array, int from, int mid, int to) {
int size = to - from;
int left = from;
int right = mid;
int dest = 0;
long[] other = new long[size];
while (left < mid && right < to) {
if (array[left] <= array[right]) {
other[dest++] = array[left++];
} else {
other[dest++] = array[right++];
}
}
while (left < mid) {
other[dest++] = array[left++];
}
while (right < to) {
other[dest++] = array[right++];
}
for (int i = 0; i < size; i++) {
array[from + i] = other[i];
}
}
3.快速排序(属于交换排序)
原理
-
总览
1.
从待排序区间选择一个数,作为基准值
(pivot)
;
2. Partition:
遍历整个待排序区间,将比基准值小的(可以包含相等的)放到基准值的左边,将比基
准值大的(可以包含相等的)放到基准值的右边;
3.
采用分治思想,对左右两个小区间按照同样的方式处理,直到小区间的长度
== 1
,代表已经有序, 或者小区间的长度 == 0
,代表没有数据。
时间复杂度:O(n*log(n)) ,不具备稳定性
代码如下:
public void SortQuilk(long[] array,int from,int to){
if(to-from<=0){
return;
}
int pi = PartitionMethodC(array,from,to);
SortQuilk(array,from,pi-1);
SortQuilk(array,pi+1,to);
}
private int PartitionMethodC(long[] array,int from,int to){
int s= from;
long pivot = array[to];
for (int i = from; i < to; i++) {
if(array[i] <pivot){
long t =array[i];
array[i] = array[s];
array[s] = t;
s++;
}
}
array[to] = array[s];
array[s] = pivot;
return s;
}
4.堆排序(属于选择排序)
时间复杂度:O(n*log(n)) ,不具备稳定性。
原理:
基本原理也是选择排序,只是不在使用遍历的方式查找无序区间的最大的数,而是通过堆来选择无序区间的最大的数。
注意:
排升序要建大堆;排降序要建小堆。
代码如下:
// 堆排序就是 建堆后 ,将第一个最大的元素和最后一个元素交换,后向下调整后,重复循环
public void Sort(long[] array){
createHeap(array);
for (int i = 0; i < array.length-1; i++) {
swap(array,0,array.length-1-i);
shiftDown(array,array.length-1-i,0);
}
}
// 建堆
public void createHeap(long[] array){
for(int i = (array.length-2)/2;i>=0;i--){
shiftDown(array,array.length,i);
}
}
private void shiftDown(long[] array, int size, int index) {
// TODO: 2022/3/17 向下调整,构建大堆 index > maxIdex
while(index*2+1<size){
int maxIdex = index*2+1;
int right = index*2+2;
if(right<size && array[right]>array[maxIdex]){
maxIdex =right;
}
if(array[index]<array[maxIdex]){
swap(array,index,maxIdex);
}
index = maxIdex;
}
}