各种排序

来源:互联网 发布:java 7年工作经验 编辑:程序博客网 时间:2024/06/05 11:19

快速排序:

     /* 快速排序 */     //直接交换,better    static int partition(Integer arr[],int low,int high){        int temp,pivot = arr[high];         while(low < high){                     /* 查找顺序要和基准选取方向相反;              pivot = arr[high] 则必须先从low开始;               反之 pivot = arr[low], 则必须先从high开始查找 */            while(arr[low] <= pivot && low < high)                low++;             arr[high] = arr[low];//直接覆盖原先的元素            while(arr[high] >= pivot && low < high)                high--;              arr[low] = arr[high];        }        // 校准,将基准移至正确位置        arr[low] = pivot;        System.out.println("low="+low+";high="+high);        return low;    }     static void  quickSort(Integer []arr,int low,int high){         if(low < high){          int pivotpos = partition(arr,low,high);          quickSort(arr,low,pivotpos-1);          quickSort(arr,pivotpos+1,high);         }    }

另一种:

    static int partition(Integer a[], int low, int high) {        int i = low, j = high;        int temp, pivot = a[i];        while (i < j) {            /*             * 查找顺序要和基准选取相反; pivot = arr[high] 则必须先从low开始;              * 反之 pivot =arr[low],则必须先从high开始查找             */            /**             * 注意:             * 1,与pivot比较必须是>=,否则在a[j]或a[i]==pivot时,会造成死循环             * 2,内层循环的i<j,保证i,j不会越过对方,因此跳出最外层循环时,i==j             */            while (a[j] >= pivot && i < j)                j--;            while (a[i] <= pivot && i < j)                i++;            // i,j位置元素,两边交换,此时无需判断i<=j,此条件在该循环中恒成立            int t = a[i];            a[i] = a[j];            a[j] = t;        }        // 校准,将基准值移至正确位置,此时i==j        a[low] = a[i];        a[i] = pivot;        System.out.println("i=" + i + ";j=" + j);// i j必相等        return i;// 返回基准所在位置划分位置    }    static void quickSort(Integer[] a, int low, int high) {        if (low < high) {            int pivotpos = partition(a, low, high);            quickSort(a, low, pivotpos - 1);            quickSort(a, pivotpos + 1, high);        }    }    public static void main(String[] args) {         Integer a[] = { 8,1,4,9,0,3,5,2,7,6};        quickSort(a, 0, a.length - 1);        Arrays.toString(a);    }

第二种
low处自始至终放的是pivot没动,最后需要把i,j指向位置的元素放到low处;
解释为什么满足放到low处:
内层两个while,先从high走,再走low;最后一次while时肯定是先不满足第一个while,第二个while又是i==j不满足;不满足第一个while但是又进得了外层的while,只能说明最后i(或j)指向的元素不满足>=pivot,即元素肯定小于pivot,所以必定满足放到low处。
这也就是为什么“查找顺序要和基准选取的方向相反

归并排序:

//将有二个有序数列a[first...mid]和a[mid...last]合并。  void mergearray(int a[], int first, int mid, int last, int temp[])  {      int i = first, j = mid + 1;      int m = mid,   n = last;      int k = 0;      while (i <= m && j <= n)      {          if (a[i] <= a[j])              temp[k++] = a[i++];          else              temp[k++] = a[j++];      }      while (i <= m)          temp[k++] = a[i++];      while (j <= n)          temp[k++] = a[j++];      for (i = 0; i < k; i++)          a[first + i] = temp[i];  }  void mergesort(int a[], int first, int last, int temp[])  {      if (first < last)      {          int mid = (first + last) / 2;          mergesort(a, first, mid, temp);    //左边有序          mergesort(a, mid + 1, last, temp); //右边有序          mergearray(a, first, mid, last, temp); //再将二个有序数列合并      }  }  bool MergeSort(int a[], int n)  {      int *p = new int[n];      if (p == NULL)          return false;      mergesort(a, 0, n - 1, p);      delete[] p;      return true;  }  

归并排序的效率是比较高的,设数列长为N,将数列分开成小数列一共要logN步,每步都是一个合并有序数列的过程,时间复杂度可以记为O(N),故一共为O(N*logN)。因为归并排序每次都是在相邻的数据中进行操作,所以归并排序在O(N*logN)的几种排序方法(快速排序,归并排序,希尔排序,堆排序)也是效率比较高的。
https://visualgo.net/sorting 排序可视化

堆排序

计算堆化时间复杂度时,将父节点与子节点的比较简易化,看本质(其实就是从上到下的单支链表!因为选择堆化结点时,是先从n/2处向前遍历。从上到下比较时,调整的必是或左或右的一颗子树。其实无论是否下面的一堆化,向下调整时,每次选择必走的是单支的啊。。。),其实是该节点的深度(树高H-本层高度h)
http://blog.csdn.net/yuzhihui_no1/article/details/44258297
该博客代码,时间复杂度 均解释十分详细

原创粉丝点击