目录
一.交换排序
1.冒泡排序
概念:
一组数据中从位置i=0,i和i+1比较,如果i比i+1大则交换,i++然后继续比较交换,持续到j=len-1,然后j--;i继续从0开始循环len次;
这样的目的是将这组数据中最大的值放进最后,循环len次就有序了
i比i-1小,不用交换i++;
i比i+1小,交换,到最后10就被放到了后面
然后j--,继续循环
代码:
public class Sort{
//冒泡排序
public void bubbleSort(int[] arr){
for (int i = 0; i < arr.length; i++) {
for (int j = 1; j < arr.length-i; j++) {
int tmp = j-1;
if(arr[j] < arr[tmp]){
swap(arr, j, tmp);
}
}
}
}
private void swap(int[] arr, int left, int right){
int tmp = arr[left];
arr[left] = arr[right];
arr[right] = tmp;
}
}
属性:
时间复杂度:O(n^2)
空间复杂度O(1)
稳定性:稳定
2.快速排序
概念:
先选取0位置的数据,然后经过操作将左边变为比它小的数据,右边变成比它大的数据;然后把左边和右边分别选取第一个数据,再进行操作;到最后就会成为一个有序的数组;
先将left位置的元素放入tmp中,然后比较right和tmp的大小,如果right比tmp小则将right放入left中,left++,否则right--;这里4比5小,所以交换,left++
然后left和tmp比较,如果left比tmp大则将left放进right中;right--,否则left++;这里9比5大,交换然后right--;
直到left>=right停下,这个位置就是centre,将tmp放入
然后分别以centre的左边和右边两个范围进行交换,循环往复
这道题可以用递归或非递归两种形式来进行
代码:
递归:
public class Sort{
public void quickSort(int[] arr){
quick(arr,0,arr.length-1 );
}
private void quick(int[] arr,int left, int right){
if(left >= right){
return;
}
dichotomy(arr, left, right);
int centre = calCentre(arr, left, right);
quick(arr, left, centre-1);
quick(arr, centre+1, right);
}
private int calCentre(int[] arr, int left, int right){
int tmp = arr[left];
while(left < right){
while(right > left && arr[right] >= tmp){
right--;
}
arr[left] = arr[right];
while(left < right && arr[left] <= tmp){
left++;
}
arr[right] = arr[left];
}
arr[left] = tmp;
return left;
}
private void dichotomy(int[] arr, int left, int right){
int mid = (left+right)/2;
if(arr[left] < arr[right]){
if(arr[mid] < arr[left]){
}else if(arr[mid] > arr[right]){
swap(arr, left, right);
}else {
swap(arr, left, mid);
}
}else {
if(arr[mid] < arr[right]){
swap(arr, left, right);
}else if(arr[mid] > arr[left]){
}else {
swap(arr, left, mid);
}
}
}
private void swap(int[] arr, int left, int right){
int tmp = arr[left];
arr[left] = arr[right];
arr[right] = tmp;
}
}
非递归:
public class Sort{
public void quickSort(int[] arr){
queueQuick(arr,0,arr.length-1 );
}
private void queueQuick(int[] arr, int left, int right){
int centre = calCentre(arr, left, right);
Queue<Integer> queue = new LinkedList<>();
queue.offer(left);
queue.offer(centre-1);
queue.offer(centre+1);
queue.offer(right);
while(!queue.isEmpty()){
left = queue.remove();
right = queue.remove();
centre = calCentre(arr, left, right);
if(centre > left){
queue.offer(left);
queue.offer(centre-1);
}
if(centre < right){
queue.offer(centre+1);
queue.offer(right);
}
}
}
}
属性:
时间复杂度:最坏情况下,也就是当每次centre都被选中再最左边或最右边的时候,复杂度为O(n^2),最好情况为O(nlogn);
注:logn是log以2为底的n
空间复杂度:O(logn)
稳定性:不稳定
二.归并排序
概念:
如图所示,将这样一组数据先两两进行排序,然后再四四进行排序,然后整体排序,就有就变成了有序的
代码:
public class MergeSort {
public void mergeSort(int[] arr){
merge(arr,0, arr.length-1);
}
private void merge(int[] arr, int left, int right){
if(left >= right){
return;
}
int mid = (left+right)/2;
merge(arr,left,mid);
merge(arr,mid+1,right);
sort(arr, left, right, mid);
}
private void sort(int[] arr, int left, int right, int mid){
int s1 = left;
int e1 = mid;
int s2 = mid+1;
int[] tmp = new int[right-left+1];
if(e1 == s1 && s2 == right){
if(arr[s1] > arr[right]){
swap(arr, s1, right);
}
return;
}
int i =0;
while(s1 <= e1 && s2 <= right){
if(arr[s1] > arr[s2]){
tmp[i] = arr[s2];
i++;
s2++;
}else if(arr[s1] < arr[s2]){
tmp[i] = arr[s1];
i++;
s1++;
}
}
while(s2 <= right){
tmp[i] = arr[s2];
i++;
s2++;
}
while(s1 <= e1){
tmp[i] = arr[s1];
i++;
s1++;
}
for (int j = 0; j < tmp.length; j++) {
arr[left+j] = tmp[j];
}
}
}
属性:
时间复杂度:O(nlogn)
空间复杂度:O(n)
稳定性:稳定