C++编程练习(15)----“排序算法 之 归并排序“
归并排序
归并排序(Merging Sort)的原理:
假设初始序列含有 n 个记录,则可以看成是 n 个有序的子序列,每个子序列的长度为1,然后两两归并,得到 [n/2] ([ x ] 表示不小于 x 的最小整数)个长度为 2 或 1 的有序子序列;再两两归并,·······,如此重复,直至得到一个长度为 n 的有序序列为止,这种排序方法称为 2 路归并排序。
归并排序是一种较占用内存,效率高,稳定的算法。
整个排序过程如下图所示:
算法描述:
归并操作的工作原理如下:
第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
第二步:设定两个指针,最初位置分别为两个已经排序序列的起始位置
第三步:比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
重复步骤3直到某一指针超出序列尾
将另一序列剩下的所有元素直接复制到合并序列尾
具体代码如下:
1、排序前的一些准备工作,建立合适的排序需要的结构。
/********* 排序用到的结构 头文件sort_struct.h ************/
#include <ctime>
#include <cstdlib>
#define MAXSIZE 100 //要排序数组个数最大值 class SqList{
public:
int r[MAXSIZE+1];
int length;
}; /* 交换L中数组r下标为i和j的值 */
void swap(SqList *L, int i, int j)
{
int temp = L->r[i];
L->r[i] = L->r[j];
L->r[j] = temp;
} /* 显示数组内容 */
void showSqList(SqList *L)
{
for(int i=1;i<=L->length;i++)
std::cout<<L->r[i]<<" ";
std::cout<<std::endl;
} /* 为数组随机产生一串数字 */
double random(double start, double end)
{
return start+(end-start)*rand()/(RAND_MAX + 1.0);
}
void RandomCreat(SqList *L,int len)
{
double random(double,double);
srand(unsigned(time(0)));
for(int i=1;i<=len;i++)
{
L->r[i] = int(random(0,100));
}
}
2、编写主文件,实现排序与测试。
/********* C++堆排序算法 ************/
#include<iostream>
#include<time.h>
#include<Windows.h>
#include"sort_struct.h"
using namespace std; /* 将有序的SR[i...m]和SR[m+1...n]归并为有序的TR[1...n] */
void Merge(int SR[],int TR[],int i,int m,int n)
{
int j,k,l;
for(j=m+1,k=i;i<=m && j<=n;k++) //将SR中记录由小到大归并入TR
{
if(SR[i]<SR[j])
TR[k] = SR[i++];
else
TR[k] = SR[j++];
}
if(i<=m)
{
for(l=0;l<=m-i;l++)
TR[k+l] = SR[i+l]; //将剩余的SR[i...m]复制到TR
}
if(j<=n)
{
for(l=0;l<=n-j;l++)
TR[k+l] = SR[j+l]; //将剩余的SR[j...n]复制到TR
} } /* 将SR[]中相邻长度为s的子序列两两归并到TR[] */
void MergePass(int SR[],int TR[],int s,int n)
{
int i = 1;
int j;
while(i<=n-2*s+1)
{
Merge(SR,TR,i,i+s-1,i+2*s-1); //两两归并
i = i+2*s;
}
if(i<n-s+1) //归并最后两个序列
Merge(SR,TR,i,i+s-1,n);
else //若最后只剩下单个子序列
for(j=i;j<=n;j++)
TR[j] = SR[j];
} /* 对顺序表L作归并非递归排序 */
void MergeSort(SqList *L)
{
int *TR = new int[L->length+1]; //申请额外空间
int k = 1;
while (k<L->length)
{
MergePass(L->r,TR,k,L->length);
k = 2 * k; //子序列长度加倍
MergePass(TR,L->r,k,L->length);
k = 2 * k; //子序列长度加倍
}
delete[] TR;
} int main()
{
SqList *L = new SqList;
L->length = 10;
RandomCreat(L,L->length);
cout<<"排序前:";
showSqList(L); MergeSort(L);
cout<<"归并排序后:";
showSqList(L); return 0;
}
运行结果如下:
C++编程练习(15)----“排序算法 之 归并排序“的更多相关文章
- Java常见排序算法之归并排序
在学习算法的过程中,我们难免会接触很多和排序相关的算法.总而言之,对于任何编程人员来说,基本的排序算法是必须要掌握的. 从今天开始,我们将要进行基本的排序算法的讲解.Are you ready?Let ...
- 【排序算法】归并排序算法 Java实现
归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用. 基本思想 可以将一组数组分成A,B两组 依次类推,当分出来的小组只有一 ...
- 【DS】排序算法之归并排序(Merge Sort)
一.算法思想 归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法的一个非常典型的应用,指的是将两个已经排序的序列合并成一个序列的操作.其归并思想如下: 1)申请空间,使其大小为两个已经 ...
- 排序算法之归并排序(Mergesort)解析
转自:http://www.cnblogs.com/ayqy/p/4050452.html 一.归并排序的优缺点(pros and cons) 耗费心思来理解它,总要有个理由吧: 归并排序的效率达 ...
- 我的Java开发学习之旅------>Java经典排序算法之归并排序
一.归并排序 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序列:即先使每个子序列 ...
- 我的Java开发学习之旅------>Java经典排序算法之归并排序
一.归并排序 归并排序是建立在归并操作上的一种有效的排序算法,该算法是採用分治法(Divide and Conquer)的一个很典型的应用.将已有序的子序列合并,得到全然有序的序列.即先使每一个子序列 ...
- C++编程练习(16)----“排序算法 之 快速排序“
快速排序 基本思想: 通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序的目的. 算法介绍: 设要排序的 ...
- Java排序算法之归并排序
基本思想: 归并排序利用分治法,先将一个序列分成一个个子序列,然后对子序列进行排序,再把有序子序列合并为整体有序序列. 图片来自于http://www.cnblogs.com/shudonghe/p/ ...
- 数据结构与算法之PHP排序算法(归并排序)
一.基本思想 归并排序算法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,使每个子序列有序,再将已有序的子序列合并,得到完全有序的序列.该算法是采用分治法(Divid ...
随机推荐
- (五)Jquery Mobile列表
Jquery Mobile列表 一.JM列表 1.普通列表 效果: 带序号的列表 将ul换成ol 效果: 2.data-inset=& ...
- 从url中提取参数名和参数值(转)
在已知参数名的情况下,获取参数值,使用正则表达式能很容易做到.js的实现方法如下: function getValue(url, name) { var reg = new RegExp('(\\?| ...
- linear-gradient线性渐变
作者:zccst CSS3 Gradient 分为 linear-gradient(线性渐变)和 radial-gradient(径向渐变). 1,在mozila background: -moz-l ...
- pageX,clientX,screenX,offsetX区别
pageX/pageY:鼠标相对于整个页面的X/Y坐标.注意,整个页面的意思就是你整个网页的全部,比如说网页很宽很长,宽2000px,高3000px,那pageX,pageY的最大值就是它们了.特别说 ...
- ndk-stack 调试 android c++ 代码崩溃位置
在android下面使用jni来调用c++,在开发游戏是非常正常的.但是要调试c++部分却是非常麻烦的问题.如果快速定位崩溃位置呢.NDK提供了一个小工具ndk-stack. 首先,我们先配置环境,把 ...
- 安卓 canvas
[转]http://blog.sina.com.cn/s/blog_61ef49250100qw9x.html(easy) [转]http://blog.csdn.net/rhljiayou/arti ...
- java求两个集合的差集
public static void main(String[] args) {Set set = new HashSet();Set set1 = new HashSet();set.add(&qu ...
- Java动态数组
其中java动态数组: Java动态数组是一种可以任意伸缩数组长度的对象,在Java中比较常用的是ArrayList,ArrayList是javaAPI中自带的java.util.ArrayList. ...
- PHP快速按行读取CSV大文件的封装类分享(也适用于其它超大文本文件)
CSV大文件的读取已经在前面讲述过了(PHP按行读取.处理较大CSV文件的代码实例),但是如何快速完整的操作大文件仍然还存在一些问题. 1.如何快速获取CSV大文件的总行数? 办法一:直接获取文件内容 ...
- 建立ipython集群
启动controller ipcontroller -- ip = ipaddress 设置ssh免登陆 因为需要分发文件,采用ssh通信,所以需要配置ssh免登陆 分发配置文件 scp contro ...