算法成长日志——归并排序

排序过程主要是对记录的排序码进行比较和记录的移动过程,因此排序的时间复杂性以算法执行中的数据的比较次数和数据移动次数来衡量。

内部排序通过过程中所依据的原则不同可以分为三类:

1.插入排序

2.归并排序

3.快速排序

一、插入排序

直接插入排序

#include <stdio.h>
void insertSort(int a[],int n)
{
    for(int i = 1;i < n;i++)
    {
        int j = i-1;
        int index = a[i];//用一个数来记住这个将要移动的a[i]
        while(j >= 0 && index < a[j])//如果这个将要移动的数一直比前面的小,那么将不断移动它
        {
            a[j+1] = a[j];//把比它大的数字不断向后面移动
            j--;
        }
        a[j+1] = index;//最后找到了这个数字应该在的位置
    }

}
int main() {
    int a[10] = {5,3,1,2,10,7,2,0,19,4};
    insertSort(a,10);
    for(int i = 0;i < 10;i++)
    {
        printf("%d ",a[i]);
    }
    return 0;
}

插入排序的效率分析如下

 二、归并排序

思考:如何用分治的思想解决这个问题?

1.分解:将n个元素分成各含n/2个元素的子序列

2.解决:递归地用合并排序法对两个子序列排序

3.合并:合并两个已经排好的序列

 归并排序的基本思想为:将待排序列元素分成大小相致相同的两个子集合,分别对两个子集合进行排序,最终将排好的子集合合并成为所要求的排好序的集合。

#include <iostream>
#include<fstream>
#include<string>

using namespace std;

int n = 0;//全局变量n,表示从文件中读入数组a的长度

int charToInt(string str);//将读取到的字符转为对应的数字
int* fileToArray(FILE * file);//从输入文件中读取出数组大小和数组
void mergeSort(int a[],int n);//对数组a进行排序
void mergePass(int a[],int b[],int length);//通过对不同情况的分析对merge调用来对给出的数组规定步长进行排序
void merge(int a[],int b[],int left,int middle,int right);//将给出的两组数合并到一组数里面存在数组b中

/*将给出的两组数合并到一组数里面存在数组b中*/
void merge(int a[],int b[],int left,int middle,int right)
{//a表示给出的数组,b表示将两组数排好了归并到数组b中,left表示第一个数组起始,middle第一个数组结束,left第二个数组结束
    int i = left;
    int j = middle + 1;//j表示需要合并的第二个数组的起始位置
    int k = left;//用来标记数组b

    while(i <= middle && j <= right)
    {
        if(a[i] < a[j])
        {
            b[k++] = a[i++];
        }
        else if(a[i] > a[j])
        {
            b[k++] = a[j++];
        }
        else
        {
            b[k++] = a[i++];
            b[k++] = a[j++];
        }
    }

    if(i > middle && j <=right)
    {
        while(j <= right)
        {
            b[k++] = a[j++];
        }
    }
    else if(i <= middle && j >right)
    {
        while(i <= middle)
        {
            b[k++] = a[i++];
        }
    }
}

/*通过对不同情况的分析 对merge进行调用,来对给出的数组进行规定步长的排序*/
void mergePass(int a[],int b[],int length)
{//a为给出数组,b为归并后的数组,length为给出的步长
    int temp = n % (2 * length);

    if(temp == 0)
    {
        for(int i = 0;i < n;i += 2*length)
        {
            merge(a,b,i,i + length -1,i + 2*length - 1);
        }
    }
    else if(temp <= length)
    {
        int i = 0;
        for(;i < n - temp;i += 2*length)
        {
            merge(a,b,i,i + length -1,i + 2*length - 1);
        }
        int k = n - temp;
        while(k < n)
        {
            b[k] = a[k];
            k++;
        }
    }
    else if(temp > length)
    {
        int i = 0;
        for(;i < n - temp;i += 2*length)
        {
            merge(a,b,i,i + length -1,i + 2*length - 1);
        }
        merge(a,b,i,i + length - 1,n-1);
    }
}

/*对a进行排序,通过传入不同的步长,调用mergePass函数*/
void mergeSort(int a[],int n)
{
    int *b=new int [n];
    int length = 1;
    while(length < n)
    {//迭代排序,从最小的步长为1开始
        mergePass(a,b,length);
        length += length;
        mergePass(b,a,length);
        length += length;
    }

}

/*将字符转换为对应数字(非ascii)*/
int charToInt(string str)
{
    int len = str.length();
    int result = 0;
    for(int i = 0;i < len;i++)
    {
        result = result *10 + (str[i]-'0');
    }
    return result;
}

/*从文件中获取数组信息*/
int * fileToArray(FILE * file)
{//通过读出以空格为分届的字符串,将字符串转换为数字
    string str ="";
    char c=fgetc(file);
    while(c>='0' and c<='9')
    {
        str += c;
        c = fgetc(file);
    }
    n = charToInt(str);

    int * a = (int *)malloc(n*sizeof(8));
    for(int i = 0;i < n;i++)
    {
        str = "";
        c = fgetc(file);
        while(c >='0' and c <='9')
        {
            str += c;
            a[i] = charToInt(str);
            c = fgetc(file);
        }
    }
    return a;
}

int main()
{
    int * a;
    FILE* fpin;
    fpin = fopen("./mergesort.in.txt","r") ;
    if(fpin == NULL){
        printf("文件读入失败");
    }
    a = fileToArray(fpin);

    mergeSort(a,n);

    ofstream os;//创建一个文件输出流对象
    os.open("./mergesort.out.txt");//将对象与文件关联
    for(int i = 0;i < n;i++)
    {
        string str;
        str = to_string(a[i]);
        os<<str;   //将输入的内容放入txt文件中
        os<<' ';

    }
    os.close();
    fclose(fpin);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MPI(Message Passing Interface)是一种用于并行计算的编程模型和库。归并排序是一种经典的排序算法,适合并行计算。 在MPI中,可以通过发送和接收消息来实现进程间的通信。下面是一个基于MPI的归并排序的伪代码: ```python def parallel_merge_sort(data): # 获取进程总数和当前进程编号 size = MPI.COMM_WORLD.Get_size() rank = MPI.COMM_WORLD.Get_rank() # 计算每个进程要处理的数据量 chunk_size = len(data) // size remainder = len(data) % size # 将数据分发到各个进程 if rank == 0: for i in range(size): if i < remainder: chunk = data[i * (chunk_size + 1):(i + 1) * (chunk_size + 1)] else: chunk = data[remainder + i * chunk_size:remainder + (i + 1) * chunk_size] MPI.COMM_WORLD.send(chunk, dest=i, tag=0) # 接收数据 chunk = MPI.COMM_WORLD.recv(source=0, tag=0) # 对本地数据进行排序 chunk.sort() # 归并排序 for step in range(size): # 计算要交换数据的进程编号 partner = (rank + step) % size # 发送和接收数据 sendbuf = chunk recvbuf = MPI.COMM_WORLD.recv(source=partner, tag=step) if rank < partner: sendtag = step recvtag = step + size else: sendtag = step + size recvtag = step MPI.COMM_WORLD.send(sendbuf, dest=partner, tag=sendtag) chunk = merge(chunk, recvbuf) # 将排序好的数据返回 if rank == 0: result = [] for i in range(size): chunk = MPI.COMM_WORLD.recv(source=i, tag=size) result.extend(chunk) return result else: MPI.COMM_WORLD.send(chunk, dest=0, tag=size) ``` 在这个算法中,首先将原始数据分发到各个进程,然后每个进程对本地数据进行排序,接着对每个步骤进行归并排序,并且使用MPI的send和recv函数进行交换数据。最后将排序好的数据返回到主进程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值