希尔、快速、归并排序学习总结

冒泡、选择、插入排序的效率都是O(N^2),但插入排序稍微快一些
归并排序的效率是O(NlogN),希尔排序的效率大约是O(N(logN)2),快速排序需要O(N*logN)时间,希尔排序效率不稳定O(N*N(1.3~2)),理论上归并比快速还要快,但归并要创建新的数组临时存储数据减慢了速度,一般归并和快速速度不相上下。

1.希尔排序
通过加大插入排序中元素之间的间隔,并在这些有间隔的元素中进行插入排序,从而能使数据项能大跨度地移动。当这些数据项排过一趟序后,希尔排序算法减小数据项的间隔再进行排序,并依此下去。
public void shellSort(){
int inner,outer;
long temp;
int h = 1;
while (h<=nElems/3)
h=h*3+1;

    while(h>0){
        for(outer = h; outer <nElems; outer++){
            temp = theArray[outer];
            inner = outer;
            while(inner>h-1 && theArray[inner-h]>temp){
                theArray[inner] = theArray[inner-h];
                inner-=h;
            }
            theArray[inner] = temp;
        }
        h = (h-1)/3;
    }

}
递减序列中的数字互质被认为很重要,这个约束能避免每一趟的排序更有可能保持前一趟排序的效果。

2.快速排序
把数组或者子数组划分成左右两边分别进行划分算法排序,并递归的对左右两边进行排序。
public void recQuickSor(int left,int right){
int size = right-left+1;
if(size<10) {
insertionSort(left, right);
}else{
long median = medianOf3(left,right);
int partition = partitionIt(left,right,median);
recQuickSor(left,partition-1);
recQuickSor(partition+1,right);
}
}

public long medianOf3(int left,int right){
    int center = (left+right)/2;
    if(theArray[left]>theArray[center]){
        swap(left,center);
    }
    if(theArray[left]>theArray[right]){
        swap(left,right);
    }
    if (theArray[center] > theArray[right]) {
        swap(center,right);
    }
    swap(center,right-1);
    return theArray[right-1];
}

public void swap(int dex1,int dex2){
    long temp = theArray[dex1];
    theArray[dex1] = theArray[dex2];
    theArray[dex2] = temp;
}

public int partitionIt(int left,int right,long pivot){
    int leftPtr = left;
    int rightPtr = right-1;
    while (true){
        while(theArray[++leftPtr]<pivot);
        while (theArray[--rightPtr]>pivot);
        if(leftPtr >= rightPtr)
            break;
        else
            swap(leftPtr,rightPtr);
        }
    swap(leftPtr,right-1);
    return leftPtr;
}

public void insertionSort(int left,int right){
    int in,out;
    for(out = left+1;out<=right;out++){
        long temp = theArray[out];
        in = out;
        while (in>left && theArray[in-1]>=temp){
            theArray[in] = theArray[in-1];
            --in;
        }
        theArray[in] = temp;
    }
}

枢纽的选用,常见的有采用数组最右端的数据项作为枢纽,而“三数据项取中”可以有效避免枢纽过大或过小产生的效率低下,本例中也是选用“三数据取中”的方式。

3.归并排序
归并算法的中心是归并两个已经有序的数组。通过反复地分割数组,直到的到的子数组只含有一个数据项,然后再用递归的方式归并这些数组。
public void mergeSort(){
long[] workSpace = new long[nElems];
recMergeSort(workSpace,0,nElems-1);
}

public void recMergeSort(long[] workSpace,int lowerBound,int upperBound){
    if(lowerBound == upperBound){
        return;
    }else{
        int mid = (lowerBound+upperBound)/2;
        recMergeSort(workSpace,lowerBound,mid);
        recMergeSort(workSpace,mid+1,upperBound);
        merge(workSpace, lowerBound, mid + 1, upperBound);
    }
}

public void merge(long[] workSpace,int lowPtr,int highPtr,int upperBound){
    int j = 0;
    int lowerBound = lowPtr;
    int mid = highPtr-1;
    int n = upperBound-lowerBound+1;
    while (lowPtr<=mid && highPtr<=upperBound){
        if(theArray[lowPtr]<theArray[highPtr]){
            workSpace[j++] = theArray[lowPtr++];
        }else{
            workSpace[j++] = theArray[highPtr++];
        }
    }
    while (lowPtr<=mid){
        workSpace[j++] = theArray[lowPtr++];
    }
    while (highPtr<=upperBound){
        workSpace[j++] = theArray[highPtr++];
    }

    for(j=0;j<n;j++){
        theArray[lowerBound+j] = workSpace[j];
    }

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值