使用插入排序算法时出错 - 数组未完全排序。

时间:2012-11-21 10:16:15

标签: c++ algorithm quicksort insertion-sort

这是一些工作代码,它实现了Quicksort算法的修改版本,该算法使用Insertion Sort作为数组大小n > 8。我的测试数组没有完全正确排序,我认为它必须与我InsertionsortInsert的实现一致。

递归Insertionsort算法的一般形式是:

void Insertionsort(int S[], int n)
{
        if(n>1)
                Insertionsort(S,n-1);
        Insert(S,n-1);

}

void Insert(int *S, int k)
{
        int key = S[k];
        int j = k-1;
        while(j>=0 && S[j] > key)
        {
                S[j+1] = S[j];
                j--;
        }

        S[j+1] = key;
}

这是我完整的工作代码,并没有完全正确地排序:

#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;


int comparisons = 0;            
int compare_qs_m3_ins[12];  


// Function prototypes
int partition(int *S,int l, int u);                                          
void exchange(int list[], int p, int q);
void Insert(int S[], int k);                                                
void Insertionsort(int S[], int low, int hi);                           
void Quicksort_Insert_M3(int S[], int n, int p, int r);       



int main()
{
    srand (time(NULL));
    // Declare all arrays used for testing
    int S1_500[500];
    int S2_500[500];
    int S3_500[500];


    int S1_300[300];
    int S2_300[300];
    int S3_300[300];

    int S1_100[100];
    int S2_100[100];
    int S3_100[100];

    int S1_8[8];
    int S2_8[8];
    int S3_8[8];




    // Fill arrays with random integers
    for(int i=0; i<500; i++)
    {
        S1_500[i] = rand()%1000;
        S2_500[i] = rand()%1000;
        S3_500[i] = rand()%1000;
    }


    for(int i=0; i<300; i++)
    {
        S1_300[i] = rand()%1000;
        S2_300[i] = rand()%1000;
        S3_300[i] = rand()%1000;
    }


    for(int i=0; i<100; i++)
    {
        S1_100[i] = rand()%500;
        S2_100[i] = rand()%500;
        S3_100[i] = rand()%500;
    }

    for(int i=0; i<8; i++)
    {
        S1_8[i] = rand()%100;
        S2_8[i] = rand()%100;
        S3_8[i] = rand()%100;
    }

    Quicksort_Insert_M3(S1_500,500,0,499);
    compare_qs_m3_ins[0] = comparisons;
    comparisons = 0;
    Quicksort_Insert_M3(S2_500,500,0,499);
    compare_qs_m3_ins[1] = comparisons;
    comparisons = 0;
    Quicksort_Insert_M3(S3_500,500,0,499);
    compare_qs_m3_ins[2] = comparisons;
    comparisons = 0;
    Quicksort_Insert_M3(S1_300,300,0,299);
    compare_qs_m3_ins[3] = comparisons;
    comparisons = 0;
    Quicksort_Insert_M3(S2_300,300,0,299);
    compare_qs_m3_ins[4] = comparisons;
    comparisons = 0;
    Quicksort_Insert_M3(S3_300,300,0,299);
    compare_qs_m3_ins[5] = comparisons;
    comparisons = 0;
    Quicksort_Insert_M3(S1_100,100,0,99);
    compare_qs_m3_ins[6] = comparisons;
    comparisons = 0;
    Quicksort_Insert_M3(S2_100,100,0,99);
    compare_qs_m3_ins[7] = comparisons;
    comparisons = 0;
    Quicksort_Insert_M3(S3_100,100,0,99);
    compare_qs_m3_ins[8] = comparisons;
    comparisons = 0;
    Quicksort_Insert_M3(S1_8,8,0,7);
    compare_qs_m3_ins[9] = comparisons;
    comparisons = 0;
    Quicksort_Insert_M3(S2_8,8,0,7);
    compare_qs_m3_ins[10] = comparisons;
    comparisons = 0;
    Quicksort_Insert_M3(S3_8,8,0,7);
    compare_qs_m3_ins[11] = comparisons;
    comparisons = 0;

    //for(int i=0; i<12; i++)
        //cout << compare_qs_m3_ins[i] << endl;



    for(int i=0;i<499;i++)
        cout << S1_500[i] << endl;





}



int partition(int *S,int l, int u)
{
    int x = S[l];
    int j = l;
    for(int i=l+1; i<=u; i++)
    {
        comparisons++;
        if(S[i] < x)
        {   
            j++;
            swap(S[i],S[j]);
        }

    }
    int p = j;
    swap(S[l],S[p]);
    return p;
}

void swap(int &val1, int &val2)
{
    int temp = val1;
    val1 = val2;
    val2 = temp;
}


void exchange(int list[], int p, int q)
{
    int temp = list[p];
    list[p] = list[q];
    list[q] = temp;
}


int Sort3(int list[], int p, int r)
{
    int median = (p + r) / 2;
    comparisons++;
    if(list[p] <= list[median])
    {
        comparisons++;
        if(list[median]>list[r])
        {
            comparisons++;
            if(list[p]<list[r])
            {
                int temp = list[p];
                list[p] = list[r];
                list[r] = list[median];
                list[median] = temp;
            }
            else
            {
                exchange(list,median,r);
            }
        }
        else
            ;

    }
    else
    {
        comparisons++;
        if(list[p] > list[r])
        {
            comparisons++;
            if(list[median] < list[r])
            {
                int temp = list[p];
                list[p] = list[median];
                list[median] = list[r];
                list[r] = temp;
            }
            else
            {
                exchange(list,p,r);
            }
        }
        else
        {
            exchange(list,p,median);
        }

    }


    return list[r];
}


void Insert(int *S, int k)
{
    int key = S[k];
    int j = k-1;
    while(j>=0 && S[j] > key)
    {
        S[j+1] = S[j];
        j--;
        comparisons++;
    }
    comparisons++;
    S[j+1] = key;
}


void Insertionsort(int S[], int low, int hi)
{
    if((hi-low)+1>1)
        Insertionsort(S,low+1,hi);
    Insert(S,hi-low);

}


void Quicksort_Insert_M3(int S[], int n, int low, int hi)
{
    if((hi-low)<=8)
        Insertionsort(S,low,hi);
    else 
    {
        if(low < hi)
        {
            if((low+1) == hi)
            {
                comparisons++;
                if(S[low] > S[hi])
                    swap(S[low],S[hi]);
            }
            else
            {
                Sort3(S,low,hi);
                if((low+2)<hi)
                {
                    swap(S[low+1],S[(low+hi)/2]);
                    int q = partition(S, low+1, hi-1);
                    Quicksort_Insert_M3(S, n, low, q-1);
                    Quicksort_Insert_M3(S, n, q+1, hi);
                }
            }
        }
    }
}

2 个答案:

答案 0 :(得分:1)

应该按升序排序三个数组元素的函数不是:

int Sort3(int list[], int p, int r)
{

仅调用p + 2 <= r,所以

    int median = (p + r) / 2;

p < median < r在这里。设a = list[p]b = list[median]c = list[r]

    comparisons++;
    if(list[p] <= list[median])
    {
        comparisons++;
        if(list[median]>list[r])
        {
            comparisons++;
            if(list[p]<list[r])
            {

所以我们a <= bc < ba < c一起a < c < b

                int temp = list[p];
                list[p] = list[r];
                list[r] = list[median];
                list[median] = temp;

但您按顺序放置c, a, b。可能你打算在那里使用if (list[r] < list[p])

            }
            else

c <= a <= b

            {
                exchange(list,median,r);

以便按顺序排列a, c, b

            }
        }
        else
            ;

    }
    else

此处b < a

    {
        comparisons++;
        if(list[p] > list[r])
        {

c < a

            comparisons++;
            if(list[median] < list[r])
            {

然后b < c < a

                int temp = list[p];
                list[p] = list[median];
                list[median] = list[r];
                list[r] = temp;
是的,这是正确的。

            }
            else

c <= b < a

            {
                exchange(list,p,r);
            }

Okedoke。

        }
        else
        {

b < a <= c

            exchange(list,p,median);

好。

        }

    }


    return list[r];
}

为什么这个函数会返回什么?你还是不要使用返回值。

答案 1 :(得分:0)

“递归Insertionsort算法的一般形式是” - 如果你需要一个头递归算法,是的,否则更好的版本是:

void Insertionsort(int S[], int i, int n)
{
    Insert(S, i, n);
    if(i < n)
        Insertionsort(S, i+1, n);
}

这更容易理解。此外,您可能已将Insert的主体放入Insertionsort。

我不会试图找出你过于复杂的quicksort版本。一个体面的快速排序大约20行或更少(像这样 - www.algolist.net/Algorithms/Sorting/Quicksort)(并添加10或更少的插入排序)。我建议通过查看另一个实现并重写你的内容来获得更好的理解。

我相信这可能会被视为previous question的延伸。