排序算法

一. 冒泡排序

基本思想:比较大小
实现思路:将数大的下沉,小的数冒起。
伪代码:

  1. for(i=0;i<n-1;i++){
  2. for(j=0;j<n-1-i;j++){
  3. if(a[j]>a[i]){
  4. //交换a[j]和a[i]
  5. }
  6. }
  7. }

最坏时间复杂度:O(n^2)

二. 插入排序

基本思想:在要排序的一组数中,假定前n-1个数已经排好序,现在将第n个数插到前面的有序数列中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。

伪代码:

public void insertSort(int[]list){
    for(int i=0;i<list.lenght-1;i++){
        for(int j=i+1;j>0;j--){
            if(list[j]<list[j-1]){
                int tmp=list[j];
                list[j]=list[j-1];
                list[j-1]=tmp;
            }
        }
    }
}

最坏时间复杂度:O(n2)

三. 选择排序

基本思想:在长度为N的无序数组中,第一次遍历n-1个数,找到最小的数值与第一个元素交换;
第二次遍历n-2个数,找到最小的数值与第二个元素交换;
。。。
第n-1次遍历,找到最小的数值与第n-1个元素交换,排序完成。
伪代码:

public void selectionSort(int[]list){
    for(int i=0;i<list.lenght;i++){
        int minIndex=i;
        for(j=i+1;j<list.lenght;j++){
            if(a[j]<a[minIndex]){
                minIndex=j;
            }
        }
        if(minIndex!=i){
            int tmp=a[i];
            a[i]=a[minIndex];
            a[minIndex]=tmp;
        }
    }
}

最坏时间复杂度:O(n2)

四. 快速排序

基本思想:分治
实现思路:
1.取key
2.将大于key的放右边,小于key的放左边
3.分别处理左右两边的部分,重复第2步骤
伪代码:

public void quitSort(int[]list,int left,int right){
    int pivot=list[left];
    int pl=lef;int pr=right;
    while(pl<pr){
        while(pl<pr&&list[pr]>pivot){
            pr--;
        }
        list[pl]=list[pr];
        while(pl<pr&& list[pl]<pivot){
               pl++;
        }
        list[pr]=list[pl];
    }
    list[left]=pivot;
    quitSort(list,0,left);
    quitSort(list,left+1,right);
}

最坏时间复杂度:O(n*logn)

五. 归并排序

基本思想:分治
实现思路:
1.将序列不断地拆成两个序列
2.不断地合并两个序列
2.1 设置左边序列的游标,设置右边序列的游标,设置临时数组的开始下标值
2.2 比较左边游标指定的元素值和右边游标指定的元素值,如果小的,把元素值给临时数组,当前游标下移,临时数组游标下移。
2.3 循环2.2步骤直到左游标超过中间值,或者右游标超过数组界限
2.4 将左边或右边剩余序列拷贝到临时数组
2.5 将临时数组的元素复原到原数组
伪代码:

public void mergeSort(int[] data,int left,int right){
    if(left<right){
        int mid=(left+right)/2;
        mergeSort(data,left,mid);//排序左边数组
        mergeSort(data,mid+1,right);//排序右边数组
        merge(data,left,mid,right);//合并两边数组
    }
}
public void merge(int[] data,int left,int mid,int right){
    //初始化两边数组游标
    int pl=left;int pr=mid+1;
    //初始化临时数组
    int[] tmp=new int[data.lenght];
    int k=left;
    //合并两边数组到临时数组
    while(pl<=mid&&pr<=right){
        if(a[pl]<=a[p2]){
            tmp[k++]=a[pl++];
        }else{
            tmp[k++]=a[pr++]
        }
    }
    while(pl<=mid){tmp[k++]=a[pl++];}
    while(pr<=right){tmp[k++]=a[pr++];}
    //将临时数组元素复原到原数组
    for(i=left;i<=right;i++){
        a[i]=tmp[i];
    }
}

最坏时间复杂度:O(n*logn)

经典dp、链表翻转、树相关算法