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

merge_sort using vectors works well with less than 9 inputs

本文关键字:输入 情况 sort 向量 merge 适用于      更新时间:2023-10-16

不知何故,我使用向量实现了合并排序,问题是:它在少于 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 asn";
    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();
}

这是一对合并排序示例,经过了一些优化,也许比学生的预期要多一点。

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

底部示例是自下而上的合并排序。请注意,排序后的数组可以以 a[] 或 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
        }
    }
}
相关文章: