排序方法基本介绍(5)

第七次博客:
排序方法基本介绍(5):
稳定的
冒泡排序(bubble sort) — O(n^2)
鸡尾酒排序(Cocktail sort,双向的冒泡排序) — O(n^2)
插入排序(insertion sort)— O(n^2)
桶排序(bucket sort)— O(n); 需要 O(k) 额外空间
计数排序(counting sort) — O(n+k); 需要 O(n+k) 额外空间
合并排序(merge sort)— O(nlog n); 需要 O(n) 额外空间
原地合并排序— O(n^2)
二叉排序树排序 (Binary tree sort) — O(nlog n)期望时间; O(n^2)最坏时间; 需要 O(n) 额外空间
鸽巢排序(Pigeonhole sort) — O(n+k); 需要 O(k) 额外空间
基数排序(radix sort)— O(n·k); 需要 O(n) 额外空间
Gnome 排序— O(n^2)
图书馆排序— O(nlog n) with high probability,需要 (1+ε)n额外空间
不稳定的
选择排序(selection sort)— O(n^2)
希尔排序(shell sort)— O(nlog n) 如果使用最佳的现在版本
组合排序— O(nlog n)
堆排序(heapsort)— O(nlog n)
平滑排序— O(nlog n)
快速排序(quicksort)— O(nlog n) 期望时间,O(n^2) 最坏情况; 对于大的、乱数列表一般相信是最快的已知排序
Introsort— O(nlog n)
耐心排序— O(nlog n+ k) 最坏情况时间,需要 额外的 O(n+ k) 空间,也需要找到最长的递增子串行(longest increasing subsequence)
不实用的
Bogo排序— O(n× n!) 期望时间,无穷的最坏情况。
Stupid sort— O(n^3); 递归版本需要 O(n^2) 额外存储器
珠排序(Bead sort) — O(n) or O(√n),但需要特别的硬件
Pancake sorting— O(n),但需要特别的硬件
stooge sort——O(n^2.7)很漂亮但是很耗时
今天介绍的排序是:原地合并排序、二叉排序树排序、Gnome 排序、耐心排序剩下的不稳定排序和不实用的排序就不再一一介绍。
原地排序
原地排序就是指在排序过程中不申请多余的存储空间,只利用原来存储待排数据的存储空间进行比较和交换的数据排序。
/*

  • 原地归并
    */
    public class InPlaceMergeSort {

    private static void reverse(int[] arr, int i, int j) {
    while(i < j)
    {
    int temp = arr[i];
    arr[i++] = arr[j];
    arr[j–] = temp;
    }
    }

    // swap [bias, bias+headSize) and [bias+headSize, bias+headSize+endSize)
    private static void swapAdjacentBlocks(int arr[], int bias, int oneSize, int anotherSize) {
    reverse(arr, bias, bias + oneSize - 1);
    reverse(arr, bias + oneSize, bias + oneSize + anotherSize - 1);
    reverse(arr, bias, bias + oneSize + anotherSize - 1);
    }

    private static void inplaceMerge(int arr[], int l, int mid, int r)
    {
    int i = l; // 指示左侧有序串
    int j = mid + 1; // 指示右侧有序串
    while(i < j && j <= r) //原地归并结束的条件。
    {
    while(i < j && arr[i] <= arr[j])
    {
    i++;
    }
    int index = j;
    while(j <= r && arr[j] <= arr[i])
    {
    j++;
    }
    swapAdjacentBlocks(arr, i, index-i, j-index);
    i += (j-index);
    }
    }

    public static void mergeSort(int arr[], int l, int r)
    {
    if(l < r)
    {
    int mid = (l + r) / 2;
    mergeSort(arr, l, mid);
    mergeSort(arr, mid + 1, r);
    inplaceMerge(arr, l, mid, r);
    }
    }

    private static void print(int[] arr) {
    for (int i : arr) {
    System.out.print(i+", ");
    }
    System.out.println();
    }

    /* 测试用例 /
    public static void main(String[] args) {
    int[] arr = {3,5,1,7,0,6,9,11};
    mergeSort(arr, 0, arr.length-1);
    print(arr);
    }
    }
    二叉排序树
    二叉排序树(Binary Sort Tree),又称二叉查找树(Binary Search Tree),亦称二叉搜索树。
    Java代码
    /
    *
    *方法名称:delete()
    *方法描述:删除结点
    *@param采用递归的方式进行删除
    *@returnString
    *@Exception
    */
    private void deleteNode(BinarySortTree p)
    {
    //TODOAuto-generatedmethodstub
    if(p!=null)
    {
    //如果结点有左子树
    /*1。若p有左子树,找到其左子树的最右边的叶子结点r,用该叶子结点r来替代p,把r的左孩子
    作为r的父亲的右孩子。
    2。若p没有左子树,直接用p的右孩子取代它。
    */
    if(p.lChild!=null)
    {
    BinarySortTree r=p.lChild;
    BinarySortTree prev=p.lChild;
    while(r.rChild!=null)
    {
    prev=r;
    r=r.rChild;
    }
    p.data=r.data;
    //若r不是p的左子树,p的左子树不变,r的左子树作为r的父结点的右孩子结点
    if(prev!=r)
    {
    prev.rChild=r.lChild;
    }
    else
    {
    //若r是p的左子树,则p的左子树指向r的左子树
    p.lChild=r.lChild;
    }
    }
    else
    {
    p=p.rChild;
    }
    }
    }
    侏儒排序
    侏儒排序(Gnome sort或Stupid sort)是一种排序算法,最初由伊朗计算机工程师Hamid Sarbazi-Azad博士(谢里夫理工大学计算机工程教授)于2000年提出并被称为“愚蠢排序”(不是 与bogosort混淆),然后由Dick Grune描述并命名为“gnome sort”。 它是一种类似于插入排序的排序算法,除了将元素移动到适当的位置是通过一系列交换完成的,如冒泡排序。 它在概念上很简单,不需要嵌套循环。 平均或预期的运行时间是O(n2),但如果列表最初几乎排序,则倾向于O(n)。
    这是使用从零开始的数组的gnome排序的伪代码:

public static void gnomeSort(int[] arr) {
int i=1;
while(i<arr.length) {
if(i==0||arr[i]>=arr[i-1]) {
i++;
}else {
int t=arr[i];
arr[i]=arr[i-1];
arr[i-1]=t;
i–;
}
}
}
耐心排序
在计算机科学中,耐心排序(Patience Sort)是将数组的元素分类成很多堆再串接回数组的一种排序算法。受到纸牌游戏耐心的启发和命名。算法的变体有效地计算给定阵列中最长的增加子序列的长度。
package ttt;

import java.util.ArrayList;
import java.util.List;

public class PatienceSort {
public static int[] patienceSort(int[] theArray) {
List new_list = new ArrayList();
for(int i = 0; i < theArray.length; i++) {
List bucket_list = new ArrayList();
if (i == 0) {
bucket_list.add(theArray[i]);
new_list.add(bucket_list);
}else {
boolean is_ok = false;
for(int j = 0; j < new_list.size(); j++) {
if(theArray[i] < (int)((List)new_list.get(j)).get(0)) {
((List)new_list.get(j)).add(0, theArray[i]);
is_ok = true;
break;
}
}
if(!is_ok) {
bucket_list.add(theArray[i]);
new_list.add(bucket_list);
}
}
}
//多维数组变成单维数组
int []ok_list = new int[theArray.length];
int q = 0;
for(int m = 0; m < new_list.size(); m++) {
for(int n = 0; n< ((List)new_list.get(m)).size(); n++) {
ok_list[q] = (int) ((List)new_list.get(m)).get(n);
q++;
}
}

    //插入循环
    int n = ok_list.length;//将数组的长度赋给n是为了防止每次for循环中判断时都调用length方法影响性能
    int tmp;//用于中转数据
    int j;
    for(int i = 1; i < n;i++){//排序的次数
        tmp = ok_list[i];
        for(j = i-1; j>=0 && ok_list[j]>tmp; j--) {//取i前面的所有跟i位置元素进行比较,先比较i-1和i,如果i-1大于i,则互换位置,i-1和i-2比较,以此类推
        	ok_list[j+1] = ok_list[j];
        }
        ok_list[j+1]= tmp;
    }
	return ok_list;
}
public static void main(String[] args) {
	int []the_array = {6, 4, 5, 1, 8, 7, 2, 3};
    System.out.print("之前的排序:");
    for(int i = 0; i < the_array.length; i++) {
        System.out.print(the_array[i] + " ");
    }
    
    int []result_array = patienceSort(the_array);
    
    System.out.print("耐心排序:");
    for(int i = 0; i < result_array.length; i++) {
        System.out.print(result_array[i] + " ");
    }
}

}
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值