java排序算法

1.直接插入排序

   思想:每一趟将一个待排的元素作为关键字,按照其关键字的大小插入到已经排好序的部分序列的适当位置上,直到插入完成。

   描述:把一个数组分成两部分,

                    第一部分:数组中的第一个值(因为只有一个值,所以被认为是已经排好序的数组),

                    第二部分:数组中剩余的值;

             从第二部分的第一个值开始往第一部分里比较插入,所以叫直接插入排序

   实现:

1
2
3
4
5
6
7
8
9
10
11
public static void insertSort(int arr[]){
    for (int i=1;i<arr.length;i++){ //从第二个值开始插
        int value=arr[i]; //待插入的元素
        int post=i;
        while(post>0 && arr[post-1]>value){
            arr[post]=arr[post-1];
            post--;
        }
        arr[post]=value; //找到其插入位置
    }
}

   时间复杂度:

       最好:O(n)

       最坏:O(n2)

       平均:O(n2)       

   空间复杂度:O(1)

   稳定性:平稳 

 


2.冒泡排序

    思想: 是一系列交换动作完成的。

    第一趟:第一个元素跟第二个比较,若果前者大于后者,两者位置交换,一次两两比较,直到最大的元素到最后的位置。

    第二趟:第一个元素跟第二个比较,一直比较到n-1

   实现:

1
2
3
4
5
6
7
8
9
10
11
12
//冒泡排序基础版
    public static void bubbleSort1(int[] arr,int n){   
        for(int i=n-1;i>0;i--){ //外层循环比较n-1次:第一次确定最后一个位置上的值,最后确定第二个位置上的值即可
            for (int j=0;j<i;j++){ //内层循环
                if(arr[j]>arr[j+1]){
                    int temp=arr[j+1];
                    arr[j+1]=arr[j];
                    arr[j]=temp;
                }
            }
        }
    }
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//冒泡排序改进版
  public static void bubbleSort2(int[] arr,int n){
      for(int i=n-1;i>0;i--){
          int flag=0;
          for (int j=0;j<i;j++){
              if(arr[j]>arr[j+1]){
                  int temp=arr[j+1];
                  arr[j+1]=arr[j];
                  arr[j]=temp;
                  flag=1;  //若发生交换,则设标记为1
                }
              }
            if (flag==0)   
             {return;} 
      }
  }

3.选择排序

思想:

    选择排序也是一种交换排序,和冒泡排序有一定的相似度,可以认为是冒泡的一种改进。
    1. 在未排序的序列中找到最大或最小值,放到排序序列的起始位置
    2. 从剩余未排序的元素中继续寻找最大(小)元素,放到已排序列的末尾。
    3. 重复第二步,直到所有的元素均排序完毕。

实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class SelectSort {
        //使序列递增
    public static void selectSort(int[] arr,int n){ 
        if((arr==null)||(arr.length==0))
            return;
        for (int i = 0; i < n; i++) {
            int min = i;//无序区的最小数据数组下标
                                // 循环查找最小值
            for (int j = i + 1; j < n; j++) { //在无序区中找到最小数据并保存其数组下标
                if (arr[min] > arr[j]) {
                    min = j;
                }
            }
            if (min != i) {
                int temp = arr[i];
                arr[i] = arr[min];
                arr[min] = temp;
            }
        }
    }  
}
  

4.快速排序

 思想:

     1. 定义两个指针,分别指向数组的第一个元素和最后一个元素。

     2. 第一趟以第一个元素为基准,从后向前扫描,直到遇到比基准小的值,交换两个指针上的值; 换方向从前向后扫描,直到遇到比基准大的值,交换两个指针上的值。
     当首尾两个指针重合时,指针指向的值为基准;将其指向的值与基准互换。

     3. 分别递归对前后两部分进行快排。

 实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class QuickSort{
    public static void quickSort3(int[] arr,int low,int high){
        if (low>high){
           return;
        }
        int i=low;
        int j=high;
        int temp=arr[low];
        while (i!=j){
            while(i<j&&temp<=arr[j]) {j--;}
             if (i<j){
             arr[i]=arr[j];
             i++;
             }
             
            while (i<j&&temp>=arr[i]){i++;}
            if(i<j){
             arr[j]=arr[i];
             j--;
            }
         }
        arr[i]=temp;
        quickSort(arr,low,i-1);
        quickSort(arr,i+1,high);
    }
}

 5.归并排序

 思想:将两个有序的数组合并为一个有序的数组;分治法,利用递归将数组分解为长度的1的数组,再将数组合并为有序的。

 实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class Merge_Sort {
    public static void sort(int[] a,int left,int right){
        int mid = (left+right)/2
        if(left<right){
            sort(a,left,mid);
            sort(a,mid+1,right);
            //左右归并
            merge(a,left,mid,right);
        }
    }
    //把两个有序的合并为一个有序的
    public static void merge(int[] arr,int l,int m,int r){
        int[] temp = new int [r-l+1];
        int i=l;
        int j=m+1;
        int k=0;
        //把两者较小的 添加到新数组中
        while (i<=m &&j<=r){
            if (arr[i]<arr[j])
                temp[k++]=arr[i++];
            else
                temp[k++]=arr[j++];
        }
        //把左边剩余的数添加到新数组中
        while(i<=m){
            temp[k++]=arr[i++];
        }
        //把右边剩余的数添加到新数组中
        while(j<=r){
            temp[k++]=arr[j++];
        }
        //把新数组中 的数在赋给原数组
        for(int x=0;x<temp.length;x++){
            arr[l+x]=temp[x];
            //System.out.print(arr[l+x]+" ");
        }   
    }
}

6.堆排序

思想:(以大顶堆为例)

堆调整(heapify):父节点的值最大,若果不是,就交换,并递归对交换后的节点进行调整。保证堆顶元素最大。

建堆:从最后一个非叶节点向上做调整。

堆排序(降序):把大顶堆的根节点和最后一个节点交换,保证最大的节点在最后一个位置上。因为交换完已经不是一个堆了,所以需要再次从根节点做heapify.

第二趟,把当前各节点和当前最后一个位置上的节点交换,依次.....

实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
public class Heap_Big {
    //对每个节点的左右字节点和自身建立一个大顶堆
    public static void heapify(int[] tree, int n, int i){
        if (i>=n)
         return ;
        int c1 = 2 * i + 1 ;
        int c2 = 2 * i + 2 ;
        int max = i ;
        if (c1 < n && tree[max]< tree[c1] )
            max = c1 ; 
        if (c2 < n && tree[max]< tree[c2] )
            max = c2 ;
        if (max != i){
            swap(tree, max, i);
            heapify(tree, n, max);//递归对交换完以后的节点建立一个大顶堆
        }
    }
 
    private static void swap(int[] tree, int i, int j) {
        int temp = tree[i];
        tree[i] = tree[j];
        tree[j] = temp;
    }
     
    //对一组数建立一个大顶堆
    public static void build_heap(int[] tree, int n){
        int last_node=n-1;
        int parent=(last_node-1)/2;
        for (int i=parent;i>=0; i--){
            heapify(tree, n, i);
        }
    }
     
    //堆排序:把大顶堆的根节点和最后一个节点交换,保证最大的节点在最后一个位置上,
    //因为交换完已经不是一个堆了,所以需要再次从根节点做heapify.第二趟,把当前各节点和当前最后一个位置上的节点交换,
    public static void heap_sort(int [] tree, int n){
        build_heap(tree,n);
        for (int i=n-1;i>=0;i--){
          swap(tree,i,0);
          heapify(tree,i,0);
        }
    }
        public static void main(String[] args) {
        int[] array = {4,10,5,3,1,2};
        int n=array.length;
        heapify(array,n,0);
        System.out.println("heapify的过程:");
        for (int i=0;i<n;i++){
            System.out.print(array[i]+" ");
        }
 
        System.out.println();
        build_heap(array,n);
        System.out.println("建堆的过程:");
        for (int i=0;i<n;i++){
            System.out.print(array[i]+" ");
        }
         
        System.out.println();
        heap_sort(array,n);
        System.out.println("堆排序的结果");
        for (int i=0;i<n;i++){
            System.out.print(array[i]+" ");
        }
    }
}

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//小顶堆<br>public class Heap_Small {<br>        //小顶堆调整的过程 
    public static void heapify2(int[] tree,int n, int i){
        if(i>=n)
         return;
        int c1=2 * i +1;
        int c2=2*i+2;
        int min=i;
        if (c1<n && tree[c1]<tree[min])
            min=c1;
        if (c2<n && tree[c2]<tree[min])
            min=c2;
        if (min != i){
            swap(tree,min,i);
            heapify2(tree,n,min);
        }
    }
     
    private static void swap(int[] tree, int i, int j) {
        int temp=tree[i];
        tree[i]=tree[j];
        tree[j]=temp;
    }<br>        //从一组数中建小顶堆
    public static void build_heap2(int[] tree,int n){
        int lastnode=n-1;
        int par=(lastnode-1)/2;  //从最后一个非叶节点开始调整
        for(int i=par;i>=0;i--){
            heapify2(tree,n,i);
        }
    }
     
    public static void heap_sort_small(int[] tree,int n){
        build_heap2(tree,n);
        //交换堆顶和当前堆的最后一个元素,确保最小的元素在最后一个位置上,由于交换以后的结果就不是小顶堆了,所以要进行heapify
        //第二趟,在交换当前堆顶元素和最后一个元素,heapify
        for (int i=n-1;i>=0;i--){
            swap(tree,0,i);
            heapify2(tree,i,0);
        }
    }<br>
       //小顶堆的插入
       public static void heapInsert(int[] tree,int n,int num){
        int i,j;
        i=n;j=(n-1)/2;
        while(j>=0 && i!=0){
            if (tree[j]<=num)
                break;
            tree[i]=tree[j];
            i=j;
            j=(i-1)/2;
        }
        tree[i]=num;
    }<br>
        //测试
        public static void main(String[] args) {
        int[] array = {10,4,5,3,1,2};
        int n=array.length;
        build_heap2(array,n);
        //heapify2(array,n,0);
        System.out.println("建堆的过程:");//建好的堆为:1 3 2 10 4 5
        for (int i=0;i<n;i++){
            System.out.print(array[i]+" ");
        }
         
        System.out.println();
 
        heap_sort_small(array,n);
        //heapify2(array,n,0);
        System.out.println("堆排序的结果为");//建好的堆为:1 3 2 10 4 5
        for (int i=0;i<n;i++){
            System.out.print(array[i]+" ");
        }
        System.out.println();
 
        int[] array2 = {10 ,30 ,20 ,100 ,40 ,50,14};
        heapInsert(array2,6,14);
        System.out.println("小顶堆中插入一个数");//建好的堆为:1 3 2 10 4 5
        for (int i=0;i<array2.length;i++){
            System.out.print(array2[i]+" ");
        }
    }
}

7.希尔排序

思想:

   1.希尔排序是对插入排序的改进。

   2. 把较大的数据集合先分为若干小组(逻辑上分组),然后对每一个小组分别进行插入排序。

实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class ShellSort {
    public static void main(String[] args) {
        int[] arr={3,5,2,7,4,8,3,9};
        shellSort(arr);
        for(int i=0;i<arr.length;i++){
            System.out.print(arr[i]+" ");
        }
    }
    public  static void shellSort(int [] arr){
        int n=arr.length;
        //分组,开始时增量为数组长度的一半
        for(int gap=n/2;gap>0;gap/=2){
            //对分组进行插入
            for(int i=gap;i<n;i++){
                //将arr[i] 插入正确的位置上
               insert(arr,gap,i);
            }
        }
    }
     
    private static void insert(int[] arr,int gap,int i){
        int value=arr[i];
        int j;
        for( j=i-gap; j>=0 && value<arr[j];j-=gap ){
            arr[j+gap]=arr[j];
        }
        arr[j+gap]=value;
    }
}

 

posted @ 2020-09-03 14:45  gavinwu_bk  阅读(132)  评论(0)    收藏  举报