merge_sort使用向量适用于少于9个输入

时间:2015-01-30 21:07:30

标签: c++ algorithm sorting

不知怎的,我使用向量实现了Merge排序,问题是: 它可以在少于9个输入的情况下正常工作,但是有9个或更多输入它可以做一些我不太了解的事情,如下所示:

Input:
5-4-3-2-1   ---   6-5-4-3-2-1   ---   9-8-7-6-5-4-3-2-1
Output:
1-2-3-4-5   ---   1-2-3-4-5-6   ---   1-2-3-4-5-7-6-8-9

以下是代码:

#include "stdafx.h"
#include <vector>
#include <iostream>
using namespace std;
void showvector(vector<int> numbers){
    for (vector<int>::iterator i = numbers.begin(); i != numbers.end(); i++)
    {
        cout << *i;
        if (i != numbers.end() - 1)cout << " - ";
    }
}

vector<int> getvector(){
    vector<int> numbers(0);
    cout << "please enter you numbers :::\n''entering any characters but numbers is the end of entry''\n";
    int counter = 0;
    do{
        int newnumber = 0;
        cout << "element(" << counter << ") = ";
        counter++;      
        cin >> newnumber; getchar();
        if (cin.good())
            numbers.push_back(newnumber);
        if (cin.fail()){
            cout << "numbers are :";
            showvector(numbers);
        }
    } while (cin.good()); getchar();
    return numbers;
}

void mergesort(vector<int>& numbers);

vector<int> merge(vector<int>& one, vector<int>& two){
    cout << "\ncomparing vector one with "; showvector(one); cout << " element(s) with vector two with "; showvector(two); cout << " element(s)\n";
    vector<int>::iterator j = two.begin();
    vector<int>::iterator i;
    for (i = one.begin(); i != one.end(); i++){
        cout << "comparing " << *i << " with " << *j<<endl;
        if (*i > *j){
            cout << "exchanging " << *i << " with " << *j << endl;;
            int c = *i;
            *i = *j;
            *j = c;
            j++;
        }
    }
    if (j != two.end() && i==one.end())
        mergesort(two); 
    cout << "\npushing vector two with "; showvector(two); cout << " element(s) back to vector one with "; showvector(one); cout << " element(s)\n";    
    for (j=two.begin(); j != two.end();j++)
            one.push_back(*j);
    cout << "returning sorted vector as\n";
    showvector(one);
    return one;
}

void mergesort(vector<int>& numbers){
    if (numbers.size() > 1){        
        vector<int> halfone(numbers.begin(), numbers.begin() + numbers.size() / 2);
        mergesort(halfone);
        vector<int> halftwo(numbers.begin() + numbers.size() / 2, numbers.end());       
        mergesort(halftwo);
        numbers = merge(halfone, halftwo);
    }               
}

int main(){
    vector<int> numbers(getvector());   
    mergesort(numbers);
    cout << "\nnumbers are :";
    showvector(numbers);
    getchar();
}

1 个答案:

答案 0 :(得分:1)

这是一对合并排序示例,有些优化,可能比学生的预期要多一些。

顶部示例是自上而下合并排序。 a []是要排序的数组,b []是与[]大小相同的临时数组。通过一对递归函数来避免复制数据,这些递归函数根据递归的级别交替合并的方向。

底部示例是自下而上合并排序。请注意,排序后的数组最终可以是[]或b []。这可以通过计算通过次数来避免,如果通过次数是奇数,则在第一次通过时就地交换。

两个排序示例都使用两个数组并使用索引进行合并。主要区别在于自上而下使用递归来重复分割索引对,直到索引表示运行大小为1,然后它开始实际的合并过程,而自下而上跳过此步骤并开始运行大小为1并且立即开始合并。大部分时间都花在合并上,因此与排序所需的总时间相比,递归生成索引的额外开销很小。

自上而下合并排序

int * TopDownMergeSort(int a[], int b[], size_t n)
{
    if(n < 2)                           // if size < 2 return
        return a;
    TopDownSplitMergeAtoA(a, b, 0, n);
    return a;
}

void TopDownSplitMergeAtoA(int a[], int b[], size_t ll, size_t ee)
{
    if((ee - ll) == 1)                  // if size == 1 return
        return;
    size_t rr = (ll + ee)>>1;           // midpoint, start of right half
    TopDownSplitMergeAtoB(a, b, ll, rr);
    TopDownSplitMergeAtoB(a, b, rr, ee);
    TopDownMerge(b, a, ll, rr, ee);     // merge b to a
}

void TopDownSplitMergeAtoB(int a[], int b[], size_t ll, size_t ee)
{
    if((ee - ll) == 1){                 // if size == 1 copy a to b
        b[ll] = a[ll];
        return;
    }
    size_t rr = (ll + ee)>>1;           // midpoint, start of right half
    TopDownSplitMergeAtoA(a, b, ll, rr);
    TopDownSplitMergeAtoA(a, b, rr, ee);
    TopDownMerge(a, b, ll, rr, ee);     // merge a to b
}

void TopDownMerge(int a[], int b[], size_t ll, size_t rr, size_t ee)
{
    size_t o = ll;                          // b[]       index
    size_t l = ll;                          // a[] left  index
    size_t r = rr;                          // a[] right index

    while(1){                               // merge data
        if(a[l] <= a[r]){                   // if a[l] <= a[r]
            b[o++] = a[l++];                //   copy a[l]
            if(l < rr)                      //   if not end of left run
                continue;                   //     continue (back to while)
            while(r < ee){                  //   else copy rest of right run
                b[o++] = a[r++];
            }
            break;                          //     and return
        } else {                            // else a[l] > a[r]
            b[o++] = a[r++];                //   copy a[r]
            if(r < ee)                      //   if not end of right run
                continue;                   //     continue (back to while)
            while(l < rr){                  //   else copy rest of left run
                b[o++] = a[l++];
            }
            break;                          //     and return
        }
    }
}

自下而上合并排序

int * BottomUpMergeSort(int a[], int b[], size_t n)
{
    for(size_t s = 1; s < n; s <<= 1){      // s = run size
        size_t ee = 0;                      // init end index
        while(ee < n){                      // merge pairs of runs
            size_t ll = ee;                 // ll = start of left  run
            size_t rr = ll+s;               // rr = start of right run
            if(rr >= n){                    // if only left run
                rr = n;
                BottomUpCopy(a, b, ll, rr); //   copy left run
                break;                      //   end of pass
            }
            ee = rr+s;                      // ee = end of right run
            if(ee > n)
                ee = n;
            BottomUpMerge(a, b, ll, rr, ee);
        }
        std::swap(a, b);                    // swap a and b ptrs
    }
    return a;                               // return sorted array
}

void BottomUpCopy(int a[], int b[], size_t ll, size_t rr)
{
    while(ll < rr){                         // copy left run
        b[ll] = a[ll];
        ll++;
    }
}

void BottomUpMerge(int a[], int b[], size_t ll, size_t rr, size_t ee)
{
    size_t o = ll;                          // b[]       index
    size_t l = ll;                          // a[] left  index
    size_t r = rr;                          // a[] right index

    while(1){                               // merge data
        if(a[l] <= a[r]){                   // if a[l] <= a[r]
            b[o++] = a[l++];                //   copy a[l]
            if(l < rr)                      //   if not end of left run
                continue;                   //     continue (back to while)
            while(r < ee){                  //   else copy rest of right run
                b[o++] = a[r++];
            }
            break;                          //     and return
        } else {                            // else a[l] > a[r]
            b[o++] = a[r++];                //   copy a[r]
            if(r < ee)                      //   if not end of right run
                continue;                   //     continue (back to while)
            while(l < rr){                  //   else copy rest of left run
                b[o++] = a[l++];
            }
            break;                          //     and return
        }
    }
}