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

实验目的:
       快速排序可以按照以下的算法思想优化,并加快快速排序的速度:即当快速排序所划分的子序列的长度小于某个定值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。
使用插入排序优化快速排序的算法实现_第1张图片
 
2、 数组规模为500的时候得到如下数据。
其中第一行为k的取值、第二行为程序运行所需要的时间,单位为ms。
使用插入排序优化快速排序的算法实现_第2张图片
整体图
使用插入排序优化快速排序的算法实现_第3张图片
局部图
3、 数组规模为5000的时候得到如下数据。
其中第一行为k的取值、第二行为程序运行所需要的时间,单位为ms
 
4、 数组规模为50000的时候得到如下数据。
其中第一行为k的取值、第二行为程序运行所需要的时间,单位为ms
使用插入排序优化快速排序的算法实现_第4张图片
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;
            }

 
        }
 
 
 
 

你可能感兴趣的:(算法,优化,.net,list,测试,PIVOT)