数据结构课设个人(八):二路归并排序

本文介绍如何使用C++模板实现非递归的二次归并排序算法,针对不同数据类型(整型、双精度、字符和字符串)处理顺序表,并通过示例展示算法过程和输出结果。涉及vector和数组的使用,以及归并排序的过程和复杂度分析。
摘要由CSDN通过智能技术生成

问题描述 :

 

对于顺序存储的线性表(假定顺序表非空),使用vector或数组,实现二次归并排序的非递归算法,并输出中间及最终的排序结果。

参考函数原型:(vector版本)

(1)//一趟归并排序算法: (两路有序并为一路)

template<class ElemType>

void Merge( vector<ElemType> &A, int low,int mid,int high); //low为第1有序区的第1个元素,mid为第1有序区的最后1个元素

(2)非递归形式的两路归并排序算法

template<class ElemType>

void MergeSort( vector<ElemType> &A);

输入说明 :

第一行:顺序表A的数据元素的数据类型标记(0:int,1:double,2:char,3:string)

第二行:待排序顺序表A的数据元素(数据元素之间以空格分隔)

输出说明 :

如第一行输入值为0、1、2、3之外的值,直接输出“err”

否则:

第一行:第一趟的排序结果(数据元素之间以","分隔)

...

第n行: 最终的排序结果(数据元素之间以","分隔)

输入范例 :

0
21 25 49 25 93 62 72 8 37 16 54

输出范例 :

21,25,25,49,62,93,8,72,16,37,54
21,25,25,49,8,62,72,93,16,37,54
8,21,25,25,49,62,72,93,16,37,54
8,16,21,25,25,37,49,54,62,72,93

思路:

基本思想:将两个(或以上)的有序表组成新的有序表。
理论操作:可以把一个长度为n 的无序序列看成是 n 个长度为 1 的有序子序列 ,首先做两两归并,得到 【n / 2】(下取整)个长度为 2 的有序子序列 ;再做两两归并,…,如此重复,直到最后得到一个长度为 n 的有序序列。

实际操作:(该处给出递归做法,下方代码实现用的是非递归)

(1)调用递归,先递归左序列(L,mid),再递归有序列(mid+1,R)。此时两个子序列各自有序了,然后再调用一个归并函数将左右序列归并为一个有序序列即可

(2)归并方法:先设定一个长度为L-R+1的空的辅助空间,然后设定两个游标分别指向两个子序列的首元素,比较两个游标指向的元素大小,小的拷贝进辅助空间,然后对应游标后移一位。直到两个子序列归并结束,再将辅助空间里排好序的元素一一拷贝(覆盖)原数组。
时间效率:O(nlog2n)
空间效率:O(n)  需要一个与原始序列同样大小的辅助序列(TR)。这正是此算法的缺点。
稳定性:稳定

图解:

代码实现: 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <stdlib.h>
#include <cmath>
#include <vector>
#include <sstream>   //用于ostringstream、istringstream、stringstream这三个类
#include<stack>
#include<vector>
#include<queue>
#include<list>
using namespace std;
template<class ElemType>
void createvector( vector<ElemType> &A )
{
    ElemType tmp;
    string temp;
    getline(cin,temp);
    stringstream input(temp); //输入流
    while(input>>tmp)
        A.push_back(tmp);
}
//一趟归并排序算法: (两路有序并为一路)
template<class ElemType>
void Merge( vector<ElemType> &A,int low,int mid,int high) //low为第1有序区的第1个元素,mid为第1有序区的最后1个元素
//A包含了以mid为分界的两个连续有序区
{
    vector<ElemType>B;
    int i=0,j=0;
    for(i=low-1,j=mid;i<mid&&j<high;){
        if(A[i]<A[j])
            B.push_back(A[i++]);
        else
            B.push_back(A[j++]);
    }
    while(i<mid)
        B.push_back(A[i++]);
    while(j<high)
        B.push_back(A[j++]);
    for(int m=low-1,k=0;m<high;m++)
        //干了件蠢事,此处和下面的for循环条件都设为  最大值<high+low-1  相当于最大值小于dk才能循环,导致只有第一次归并能进行,后续start都大于dk了一次循环都无法实现
        A[m]=B[k++];
    /*    for(int i=low-1;i<high;i++)
            cout<<A[i]<<" ";
        cout<<endl;*/
}
//非递归形式的两路归并排序算法
template<class ElemType>
void MergeSort( vector<ElemType> &A)
{
    int start=1;
    int dk=1;//dk为一组有序区长度,每次待归并的为两组长度共2*dk
    int length=A.size();
    if(length==1)
        cout<<A[0]<<endl;
    while(dk<length){
        start=1;
        while(start+dk<=length){  //保证剩余的长度至少要大于一组有序区的长度,才需要去归并
                int mid=start+dk-1,high=(mid+1)+dk-1;
        if(high>length) high=length ; //最后一组长度不一定够dk个
            Merge( A,start, mid, high);
            start=high+1;  //每两组依次进行一次归并
        }
        for(int i=0;i<length-1;i++)
                cout<<A[i]<<",";
        cout<<A[length-1]<<endl;
        dk*=2;
    }
}
int main()
{
    int kd;
    cin>>kd;
    cin.ignore();
    if(kd==0){
        vector<int> A;
        createvector( A );
        MergeSort( A );
    }
    else if(kd==1){
        vector<double>A;
        createvector( A );
        MergeSort( A );
    }
    else if(kd==2){
         vector<char>A;
         createvector( A );
           MergeSort( A );
    }
     else if(kd==3){
        vector<string >A;
        createvector( A );
        MergeSort( A );
     }
    else
        cout<<"err"<<endl;
    return 0;
}

注:本题采用的是非递归解法,若采用递归解法则函数如下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值