几种排序算法 冒泡、快速排序、归并、选择排序等

来源:互联网 发布:网络高清摄像头安装方法 编辑:程序博客网 时间:2024/05/22 07:43
/**     * 快速排序     * @param arrays     * @param left     * @param right     */    public static void quickSort(int arrays[], int left, int right) {        int dp;        if (left < right) {            dp = partition(arrays, left, right);            quickSort(arrays, left, dp - 1);            quickSort(arrays, dp + 1, right);        }    }    private static int partition(int arrays[], int left, int right) {        int pivot = arrays[left];        while (left < right) {            while (left < right && arrays[right] >= pivot)                right--;            if (left < right)                arrays[left++] = arrays[right];            while (left < right && arrays[left] <= pivot)                left++;            if (left < right)                arrays[right--] = arrays[left];        }        arrays[left] = pivot;        return left;    }

步骤为:

  1. 从数列中挑出一个元素,称为"基准"(pivot),
  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。

  引用维基百科的图片和解释步骤

/**     * 冒泡排序     * @param arrays     * @return     */    public static int[] bubbleSort(int[] arrays) {        for (int i=0; i<arrays.length-2; i++) {            for (int j=i+1; j<arrays.length; j++) {                if (arrays[j] < arrays[i]) {                    int temp = arrays[j];                    arrays[j] = arrays[i];                    arrays[i] = temp;                }            }        }        return arrays;    }

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
  3. 针对所有的元素重复以上的步骤,除了最后一个。
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。


/**     * 插入排序     * @param arrays     * @return     */    public static int[] insertSort(int[] arrays) {        int i, j;        for (i=1; i<arrays.length; i++) {            int temp = arrays[i];            for (j=i-1; j>=0 && arrays[j]>temp; j--)                arrays[j+1] = arrays[j];            arrays[j] = temp;        }        return arrays;    }
  
  1. 从第一个元素开始,该元素可以认为已经被排序
  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描
  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置
  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
  5. 将新元素插入到该位置后
  6. 重复步骤2~5

如果比较操作 代价比 交换操作 大的话,可以采用二分查找法来减少比较操作的数目。该算法可以认为是插入排序的一个变种,称为二分查找插入排序。


/**     * 归并排序     *      递归算法     * @param arrays     * @return     */    public static void mergingSort(int[] arrays, int start, int end) {        int[] reg = new int[arrays.length];        int len = end - start;        if (len <= 1)            return;        int mid = (len >> 1) + start; //位运算,有符号右移 1 位, 相当于len/2        //位运算 左移1位相当于 乘以2,右移1位相当于除以2        int startLeft = start, endLeft = mid;        int startRight = mid+1, endRight = end;        mergingSort(arrays, startLeft, endLeft);        mergingSort(arrays, startRight, endRight);        int k = start;        while (startLeft <= endLeft && startRight <= endRight) {            reg[k ++] = arrays[startLeft] < arrays[startRight] ? arrays[startLeft ++] : arrays[startRight ++];        }        while (startLeft <= endLeft) {            reg[k++] = arrays[startLeft++];        }        while (startRight <= endRight) {            reg[k++] = arrays[startRight++];        }        for (int i=start; i<end; i++) {            arrays[i] = reg[i];        }        return ;    }
  1. 将序列每相邻两个数字进行归并操作,形成floor(n/2)个序列,排序后每个序列包含两个元素
  2. 将上述序列再次归并,形成floor(n/4)个序列,每个序列包含四个元素
  3. 重复步骤2,直到所有元素排序完毕

自己写的算法貌似有点问题,以后再修改


/**     * 希尔排序     * @param arrays     * @return     */    public static int[] shellSort(int[] arrays) {        int gap = 1, i, j, len = arrays.length;        int temp;        while (gap < len / 3)            gap = gap * 3 + 1; // <O(n^(3/2)) by Knuth,1973>: 1, 4, 13, 40, 121, ...        for (; gap > 0; gap /= 3)            for (i = gap; i < len; i++) {                temp = arrays[i];                for (j = i - gap; j >= 0 && arrays[j] > temp; j -= gap)                    arrays[j + gap] = arrays[j];                arrays[j + gap] = temp;            }        return arrays;    }
 

例如,假设有这样一组数[ 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 ],如果我们以步长为5开始进行排序,我们可以通过将这列表放在有5列的表中来更好地描述算法,这样他们就应该看起来是这样:

13 14 94 33 8225 59 94 65 2345 27 73 25 3910

然后我们对每列进行排序:

10 14 73 25 2313 27 94 33 3925 59 94 65 8245

将上述四行数字,依序接在一起时我们得到:[ 10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 ].这时10已经移至正确位置了,然后再以3为步长进行排序:

10 14 7325 23 1327 94 3339 25 5994 65 8245

排序之后变为:

10 14 1325 23 3327 25 5939 65 7345 94 8294

最后以1步长进行排序(此时就是简单的插入排序了)。







0 0