**数据结构经典排序
1,直接插入排序
2,希尔排序
3,选择排序
4,堆排序
5,冒泡排序
6,快速排序
7,归并排序
一 复杂度比较
二算法说明
(1)冒泡排序:
是相邻元素之间的比较和交换,两重循环O(n2);所以,如果两个相邻元素相等,是不会交换的。所以它是一种稳定的排序方法
(2)选择排序:
每个元素都与第一个元素相比,产生交换,两重循环O(n2);举个栗子,5 8 5 2 9,第一遍之后,2会与5交换,那么原序列中两个5的顺序就被破坏了。所以不是稳定的排序算法
(3)插入排序:
插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。刚开始这个小序列只包含第一个元素,事件复杂度O(n2)。比较是从这个小序列的末尾开始的。想要插入的元素和小序列的最大者开始比起,如果比它大则直接插在其后面,否则一直往前找它该插入的位置。如果遇见了一个和插入元素相等的,则把插入元素放在这个相等元素的后面。所以相等元素间的顺序没有改变,是稳定的。
(4)快速排序
快速排序有两个方向,左边的i下标一直往右走,当a[i] <= a[center_index],其中center_index是中枢元素的数组下标,一般取为数组第0个元素。而右边的j下标一直往左走,当a[j] > a[center_index]。如果i和j都走不动了,i <= j, 交换a[i]和a[j],重复上面的过程,直到i>j。 交换a[j]和a[center_index],完成一趟快速排序。在中枢元素和a[j]交换的时候,很有可能把前面的元素的稳定性打乱,比如序列为 5 3 3 4 3 8 9 10 11, 现在中枢元素5和3(第5个元素,下标从1开始计)交换就会把元素3的稳定性打乱,所以快速排序是一个不稳定的排序算法,不稳定发生在中枢元素和a[j]交换的时刻。
(5)归并排序
归并排序是把序列递归地分成短序列,递归出口是短序列只有1个元素(认为直接有序)或者2个序列(1次比较和交换),然后把各个有序的段序列合并成一个有序的长序列,不断合并直到原序列全部排好序。可以发现,在1个或2个元素时,1个元素不会交换,2个元素如果大小相等也没有人故意交换,这不会破坏稳定性。那么,在短的有序序列合并的过程中,稳定是是否受到破坏?没有,合并过程中我们可以保证如果两个当前元素相等时,我们把处在前面的序列的元素保存在结果序列的前面,这样就保证了稳定性。所以,归并排序也是稳定的排序算法。
(6)希尔排序(shell)
希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小,插入排序对于有序的序列效率很高。所以,希尔排序的时间复杂度会比o(n^2)好一些。由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。
(7)堆排序
我们知道堆的结构是节点i的孩子为2i和2i+1节点,大顶堆要求父节点大于等于其2个子节点,小顶堆要求父节点小于等于其2个子节点。在一个长为n的序列,堆排序的过程是从第n/2开始和其子节点共3个值选择最大(大顶堆)或者最小(小顶堆),这3个元素之间的选择当然不会破坏稳定性。但当为n/2-1, n/2-2, …1这些个父节点选择元素时,就会破坏稳定性。有可能第n/2个父节点交换把后面一个元素交换过去了,而第n/2-1个父节点把后面一个相同的元素没有交换,那么这2个相同的元素之间的稳定性就被破坏了。所以,堆排序不是稳定的排序算法
三 代码的编写
在这里插入代码片
```package java0324;
import java.util.Arrays;
import java.util.Stack;
public class jingdianpaixu {
//1直接排序
//思路:已排和待排区间
public static void zhipai(int[] arr){
int bound=1;
for(;bound<arr.length;bound++){
int v=arr[bound];
int cur=bound-1;
for(;cur>=0;cur--){
if(arr[cur]>v){
arr[cur+1]=arr[cur];
}else{
break;
}
}
arr[cur+1]=v;
}
}
//2希尔排序
public static void shellSort(int[] arr){
int gap=arr.length/2;
while(gap>=1){
_shellsort(arr,gap);
gap=gap/2;
}
}
public static void _shellsort(int[] arr,int gap){
int bound=gap;
for(;bound<arr.length;bound++){
int v=arr[bound];
int cur=bound-gap;
for(;cur>=0;cur-=gap){
if(arr[cur]>v){
arr[cur+gap]=arr[cur];
}else {
break;
}
}
arr[cur+gap]=v;
}
}
//3选择排序----打擂台
public static void selectsort(int[] arr){
int bound=0;
for(;bound<arr.length;bound++){
for(int cur=bound+1;cur<arr.length;cur++){
if(arr[cur]<arr[bound]){
swap(arr,cur,bound);
}
}
}
}
public static void swap(int[] arr,int x,int y){
int tmp=arr[x];
arr[x]=arr[y];
arr[y]=tmp;
}
//4,堆排序
public static void duipai(int[] arr){
//1,创建堆
createHeap(arr);
//2,交换元素
int heapsize=arr.length;
for(int i=0;i<arr.length;i++){
swap(arr,0,heapsize-1);
heapsize--;
shutdown(arr,heapsize,0);
}
}
public static void createHeap(int[] arr){
for(int i=(arr.length-1-1)/2;i>=0;i--){
shutdown(arr,arr.length,i);
}
}
//5,冒泡排序
public static void bubblesort(int[] arr){
for(int bound=0;bound<arr.length;bound++){
for(int cur=arr.length-1;cur>bound;cur--){
if(arr[cur-1]>arr[cur]){
swap(arr,cur-1,cur);
}
}
}
}
public static void shutdown(int[] arr,int size,int index){
int parent=index;
int child=(parent*2)+1;
while(child<size){
if(child+1<size&&arr[child+1]>arr[child]){
child=child+1;
}
if(arr[parent]<arr[child]){
swap(arr,parent,child);
}else{
break;
}
parent=child;
child=2*parent+1;}
}
//递归快速排序
public static void quickSort(int[] arr){
_quickSort(arr,0,arr.length-1);
}
public static void _quickSort(int[] arr,int left,int right){
if(left>=right){
return ;
}
//计算位置
int index=zms(arr,left,right);
_quickSort(arr,left,index-1);
_quickSort(arr,index+1,right);
}
public static int zms(int[] arr,int left,int right){
//选基准值
int v=arr[right];
int a=left;
int b=right;
while(a<b){
while(a<b&&arr[a]<=v){
a++;
}
while(a<b&&arr[b]>=v){
b--;
}
swap(arr,a,b);
}
swap(arr,a,right);
return a;
}
//非递归快速排序
public static void quicksortloop(int [] arr){
Stack<Integer> stack =new Stack<>();
stack.push(0);
stack.push(arr.length-1);
while(!stack.isEmpty()){
int right=stack.pop();
int left=stack.pop();
if(left>=right){
continue;
}
int index=zms(arr,left,right);
//先进右边,后进左边
stack.push(index+1);
stack.push(right);
stack.push(left);
stack.push(index-1);
}
}
// 递归归并排序
public static void mertSort(int[] arr){
_mertsort(arr,0,arr.length);
}
public static void _mertsort(int[] arr,int left,int right){
if(right-left<=1){
return;
}
int mid=(left+right)/2;
_mertsort(arr,left,mid);
_mertsort(arr,mid,right);
mert(arr,left,mid,right);
}
public static void mert(int [] arr,int left,int mid,int right){
if(left>=right){
return;
}
int[] zms=new int[right-left];
int tmp=0;
int cur1=left;
int cur2=mid;
while(cur1<mid&&cur2<right){
if(arr[cur1]<arr[cur2]){
zms[tmp]=arr[cur1];
tmp++;
cur1++;
}else{
zms[tmp]=arr[cur2];
tmp++;
cur2++;
}
}
while(cur1<mid){
zms[tmp]=arr[cur1];
tmp++;
cur1++;
}
while(cur2<right){
zms[tmp]=arr[cur2];
tmp++;
cur2++;
}
for(int i=0;i<zms.length;i++){
arr[left+i]=zms[i];
}
}
//非递归排序
public static void mergesortloop(int[] arr){
int gap=1;
for(;gap<arr.length;gap*=2){
for(int i=0;i<arr.length;i+=gap*2){
int left=i;
int mid=i+gap;
if(mid>arr.length){
mid=arr.length;
}
int right=i+2*gap;
if(right>=arr.length){
right=arr.length;
}
mert(arr,left,mid,right);
}
}
}
public static void main(String[] args){
int[] arr={9,5,2,7,3,6,8};
// zhipai(arr);
// shellSort(arr);
// selectsort(arr);
// duipai(arr);
// bubblesort(arr);
// quickSort(arr);
// quicksortloop(arr);
// mertSort(arr);
mergesortloop(arr);
System.out.println(Arrays.toString(arr));
}
}
****