\t\t使用插入排序优化快速排序的算法实现

来源:互联网 发布:深圳石油软件 编辑:程序博客网 时间:2024/05/16 12:49

实验目的:
       快速排序可以按照以下的算法思想优化,并加快快速排序的速度:即当快速排序所划分的子序列的长度小于某个定值k时,该子序列基本有序,可以采用插入排序的办法对子序列进行排序,从而使整体算法的时间复杂度的期望下降为O(nk+nlg(n/k))。本实验的目的是实现该快速排序的优化算法,并且探讨合理的k的取值范围
问题定义
实验总共要解决两个问题
1、 优化的快速排序的算法确实能够加速快速排序的速度。
2、 讨论k的合理的取值范围。
对于给定规模为n的int[]无序随机数组进行排序,通过实验证明经过优化的快速排序比传统的快排效率要高,并讨论k的值的范围。
实验思想
1、 优化快速排序的方法:
a)         在快速的排序的方法中加入判断语句,当high-low<k的时候则调用插入排序的算法,否则继续使用快速排序。
b)        当k<=2时,实质上不调用插入排序,这样就可以得出相同规模的情况下直接使用快速排序所需要的时间。从而便于比较
2、 通过考察时间消耗来确定性能的高低
a)         每次计算数据都取一定规模的int 32型无序随机数进行排序,为了避免误差,规模n一定时,不同的k值,都计算5次运算时间,取平均值记录。
b)        使用.net framework 2.0提供的Stopwatch计时器对象,该对象可以将时间间隔精确到0.0001ms。
c)         从理论上得到合理的k值的取值范围是k<=logn.因此在验证取值范围的时候要取到log n 两侧的值。
d)        通过比较时间复杂度来计算性能提升的多少,从而得到加快了快速排序的结论,以及合理的k的取值范围。
测试数据及结果
本测试的硬件以及软件环境如下
       CPU:PM 1.5G; 内存:768M;操作系统:windows xp sp2;软件平台:.net 2.0;
1、 数组规模为50的时候得到如下数据。
其中第一行为k的取值、第二行为程序运行所需要的时间,单位为ms。

  使用插入排序优化快速排序的算法实现 - 哼哈二将 - 尚武思文

2、 数组规模为500的时候得到如下数据。
其中第一行为k的取值、第二行为程序运行所需要的时间,单位为ms。

整体图

  使用插入排序优化快速排序的算法实现 - 哼哈二将 - 尚武思文

局部图


  使用插入排序优化快速排序的算法实现 - 哼哈二将 - 尚武思文

3、 数组规模为5000的时候得到如下数据。

其中第一行为k的取值、第二行为程序运行所需要的时间,单位为ms

  使用插入排序优化快速排序的算法实现 - 哼哈二将 - 尚武思文


4、 数组规模为50000的时候得到如下数据。
其中第一行为k的取值、第二行为程序运行所需要的时间,单位为ms

  使用插入排序优化快速排序的算法实现 - 哼哈二将 - 尚武思文

5、 数组规模为1,000,000的时候得到如下数据。
其中第一行为k的取值、第二行为程序运行所需要的时间,单位为ms

  使用插入排序优化快速排序的算法实现 - 哼哈二将 - 尚武思文


结果分析:
1、 由所有的图可以看出,经过优化以后的快速排序比传统快速排序的速度要快,通过数据计算可以排序速度提高了10%-20%左右。
2、 通过图示也可以知道当k=logn的时候,其效率提升并不是最大的,在规模不大(例如5个数量级以下)的排序中其最佳的k的取值往往比log n大,一般以8—12之间为最小。
当规模较大时,一般取logn为宜,即使最佳取值超过logn其性能提升也不明显。
3、 此后随着k的取值的增大,尤其是超过50之后,时间复杂度明显提升,甚至比快速排序的算法要差。
4、 在规模较大的排序过程中快速排序的效率明显好于插入排序。
有可能影响结论的因素:
1、 快速取随机数的算法:
a)         在本实验中,所使用的随机数是在10n的整数内取n个无重复的随机数,该算法有可能会影响对实验结果的分析有轻微影响。
2、 小规模的数组的分析
a)         对于小规模的数组有可能在快速排序之后得到的子序列的长度小于8,因此直接取8值得商榷。

实验结论
1、 经过优化以后的快速排序比传统快速排序的速度要快,通过数据计算可以排序速度提高了10%-20%左右。
2、 在规模不大(例如5个数量级以下)的排序中其最佳的k的取值往往比log n大,一般以8—12之间效率最佳。
当规模较大时,k的取值一般取logn为宜,即使最佳取值超过logn其性能提升也不明显。

源代码
优化排序的算法源代码(C#描述)
class SortOp
    ...{ //插入排序
        private static void InsertSort(int[] list,int low,int high)
        ...{
            for (int i = low; i < high; i++)
            ...{
                int t = list[i];
                int j = i;
                while ((j > 0) && (list[j - 1] > t))
                ...{
                    list[j] = list[j - 1];
                    --j;
                }
                list[j] = t;
            }
        }
    

    
           private static void Swap(ref int i, ref int j)
            //只有两个元素时直接交换
            ...{
                int t;
                t = i;
                i = j;
                j = t;
            }
            //快速排序优化
            public static void QuickSort(int[] list, int low, int high,int k)
            ...{  
                //只剩下一个无需交换
                if (high <= low)
               ...{
                    return;
                }
                else if (high == low + 1)
               ...{
                    //只剩下两个直接交换
                    if (list[low] > list[high])
                    ...{                   
                        Swap(ref list[low], ref list[high]);
                        return;
                    }
                }
                //大于三个元素开始优化的快速排序
                myQuickSort(list, low, high,k);
            }

            public static void myQuickSort(int[] list, int low, int high,int k)
           ...{
                if (low < high)
                ...{
                    if(high-low<k)           //子序列小于k个使用插入排序
                    ...{
                    InsertSort(list,low,high);
                    }
                    else...{
                    int pivot = Partition(list, low, high);
                    myQuickSort(list, low, pivot - 1,k);
                    myQuickSort(list, pivot + 1, high,k);
                    }
                }
            }

            private static int Partition(int[] list, int low, int high)
            ...{
                int pivot;
                pivot = list[low];
                while (low < high)
            ...{
                    while (low < high && list[high] >= pivot)
                   ...{
                        high--;
                    }
                    if (low != high)
                    ...{
                        Swap(ref list[low], ref list[high]);
                        low++;
                    }
                    while (low < high && list[low] <= pivot)
                    ...{
                        low++;
                    }
                    if (low != high)
                    ...{
                        Swap(ref list[low], ref list[high]);
                        high--;
                    }
                }
                return low;
            }

        }


来自CSDN博客,转载请标明出处:http://blog.csdn.net/icyfire0105/archive/2008/01/26/2066602.aspx

0 0
原创粉丝点击