转自:爪哇人
#include<iostream.h>
#include<time.h>
#include<stdlib.h>
#define MIN_ELEMENT_NUM 100000
#define MAX_ELEMENT_NUM 1500000
#define INCREMENT_NUM 100000
//产生随机数
double random(double start, double end)
{
return start+(end-start)*rand()/(RAND_MAX + 1.0);
}
//产生iElementNum个随机数的待排序列数组pArray[]
void fill_array(int *pArr,int num)
{
for(int i=0; i<num; i++)
pArr[i] = int(random(0,100000));
}
/********************
* 直接插入排序 *
********************/
void straight_insertion_sort(int *pArr,int size){
int post_key; //记录当前要插入的key
for(int i=1;i<size;i++){ //从第二个数据开始
post_key=pArr[i];
int j;
for(j=i-1;j>=0;j--){ //将比post_key要大的前面所有的key依次后移一位
if(post_key<pArr[j])
pArr[j+1]=pArr[j];
else
break;
}
pArr[j+1]=post_key; //将post_key插入到合适位置
}
}
/********************
* 折半插入排序 *
********************/
void binary_insertion_sort(int *pArr,int size){
int post_key;
for(int i=1;i<size;i++){
post_key=pArr[i];
int low=0,high=i-1; //折半查找
while(low<=high){
int middle=(low+high)/2;
if(post_key<pArr[middle])
high=middle-1;
else low=middle+1;
}
for(int j=i-1;j>=high+1;j--) //移动位置
pArr[j+1]=pArr[j];
pArr[high+1]=post_key;
}
}
/*****************
* 希尔排序 *
*****************/
void shell_sort(int *pArr,int size){
int increment=size; //增量
do{
increment=increment/3+1; //增量逐步减少至1
int post_key;
for(int i=increment;i<size;i++){
if(pArr[i]<pArr[i-increment]){
post_key=pArr[i];
for(int j=i-increment;j>=0&&post_key<pArr[j];j=j-increment)
pArr[j+increment]=pArr[j];
pArr[j+increment]=post_key;
}
}
}while(increment>1);
}
/*****************
* 起泡排序 *
*****************/
void bubble_sort(int *pArr,int size){
for(int i=size-1;i>=0;i--)
for(int j=0;j<i;j++)
if(pArr[j]>pArr[j+1]){
int temp=pArr[j];
pArr[j]=pArr[j+1];
pArr[j+1]=temp;
}
}
/*****************
* 快速排序 *
*****************/
void quick_sort(int *pArr, int size){
int * beginIdxs=(int *)malloc(size * sizeof(int)); //记录待调整子序列的首地址
int * endIdxs=(int *)malloc(size * sizeof(int));//记录待调整子序列的尾地址
beginIdxs[0]=0;
endIdxs[0]=size-1;
int curIdx=0;
while(curIdx>-1){
int low=beginIdxs[curIdx];
int high=endIdxs[curIdx];
int pivotkey=pArr[low]; //将第一个元素作为枢轴
while(low<high){
while(low<high && pivotkey<=pArr[high]) --high;
pArr[low]=pArr[high];
while(low<high && pivotkey>=pArr[low]) ++low;
pArr[high]=pArr[low];
}
pArr[low]=pivotkey;
int pivotidx=low;
int begin=beginIdxs[curIdx];
int end=endIdxs[curIdx];
curIdx--;
if(begin<pivotidx-1){
beginIdxs[++curIdx]=begin;
endIdxs[curIdx]=pivotidx-1;
}
if(end>pivotidx+1){
beginIdxs[++curIdx]=pivotidx+1;
endIdxs[curIdx]=end;
}
}
}
/********************
* 简单选择排序 *
********************/
void simple_selection_sort(int *pArr, int size){
for(int i=0;i<size;i++){
int min_key=pArr[i]; //存储每一趟排序的最小值
int min_key_pos=i; //存储最小值的位置
for(int j=i+1;j<size;j++){
if(min_key>pArr[j]){ //定位最小值
min_key=pArr[j];
min_key_pos=j;
}
}
pArr[min_key_pos]=pArr[i]; //将选择的最小值交换位置
pArr[i]=min_key;
}
}
/************************************************
* 树形选择排序(锦标赛排序Tournament Sort) *
************************************************/
#define MAX_INT 32767;
typedef struct sort_node{
int key; //待排关键字
int pos; //此关键字在待排序列中的位置
}SortNode;
void tree_selection_sort(int *pArr,int size){
int level=1;
SortNode **level_point;
//记录每一层的关键字容量的连续空间
int *level_count;
//记录已经排序号的关键字序列
int *sorted_keys;
//开辟存储排序序列的容量
sorted_keys=(int *)malloc(size*sizeof(int));
//根据待排序列的数量确定排序树的层次
int a_size=size;
bool isPower=true;
if(a_size>1){
while(a_size!=1){
if(a_size%2==1)
isPower=false;
level++;
a_size/=2;
}
}
if(isPower==false) level++;
//构造排序树的内存结构,为每一层开辟可以容纳一定数量关键字的内存空间
level_point=(SortNode **)malloc(level*sizeof(SortNode *));
level_count=(int *)malloc(level*sizeof(int));
int level_size=size;
for(int l=0;l<level;l++){
level_count[l]=level_size;
level_point[l]=(SortNode *)malloc(level_size*sizeof(SortNode));
level_size=level_size/2+level_size%2;
}
//为第0层赋值待排序列,并建立排序树,找到第一次最小的关键字
for(int i=0;i<size;i++){
level_point[0][i].key=pArr[i];
level_point[0][i].pos=i;
}
int cur_level=1;
while(cur_level<level){
for(int j=0;j<level_count[cur_level];j++){
int left_child=level_point[cur_level-1][j*2].key;
//没有右孩子
if((j*2+1)>=level_count[cur_level-1]){
level_point[cur_level][j].key=left_child;
level_point[cur_level][j].pos=level_point[cur_level-1][j*2].pos;
}else{
int right_child=level_point[cur_level-1][j*2+1].key;
level_point[cur_level][j].key=left_child<=right_child ? left_child : right_child;
level_point[cur_level][j].pos=left_child<=right_child ? level_point[cur_level-1][j*2].pos : level_point[cur_level-1][j*2+1].pos;
}
}
cur_level++;
}
//第一次树形排序的最小值和最小位置
int cur_min_key=level_point[level-1][0].key;
int cur_min_pos=level_point[level-1][0].pos;
sorted_keys[0]=cur_min_key;
//输出剩下size-1个最小的数
for(int count=1;count<=size-1;count++){
level_point[0][cur_min_pos].key=MAX_INT;
//找到需要重新比较的两个位置
int a_pos=cur_min_pos;
int b_pos=a_pos%2==0 ? a_pos+1 : a_pos-1;
for(int m=1;m<level;m++){
if(b_pos>=level_count[m-1]){
level_point[m][a_pos/2].key=level_point[m-1][a_pos].key;
level_point[m][a_pos/2].pos=level_point[m-1][a_pos].pos;
}else{
level_point[m][a_pos/2].key=level_point[m-1][a_pos].key<=level_point[m-1][b_pos].key ? level_point[m-1][a_pos].key : level_point[m-1][b_pos].key;
level_point[m][a_pos/2].pos=level_point[m-1][a_pos].key<=level_point[m-1][b_pos].key ? level_point[m-1][a_pos].pos : level_point[m-1][b_pos].pos;
}
a_pos=a_pos/2;
b_pos=a_pos%2==0 ? a_pos+1 : a_pos-1;
}
//记录每一次树形排序的最小值和对应的位置
cur_min_key=level_point[level-1][0].key;
cur_min_pos=level_point[level-1][0].pos;
sorted_keys[count]=cur_min_key;
}
free(level_count);
free(sorted_keys);
for(int k=0;k<level;k++)
free(level_point[k]);
}
/***************
* 堆排序 *
***************/
//交换
void swap(int *pArr,int pos_a,int pos_b){
int temp=pArr[pos_a];
pArr[pos_a]=pArr[pos_b];
pArr[pos_b]=temp;
}
//创建堆
void create(int *pArr,int size){
for(int i=(size-1)/2;i>=0;i--){
int lchild=i*2+1;
int rchild=i*2+2;
while(lchild<size){
int next_pos=-1;
if(rchild>=size&&pArr[i]>pArr[lchild]){
swap(pArr,i,lchild);
next_pos=lchild;
}
if(rchild<size){
int min_temp=pArr[lchild]<=pArr[rchild] ? pArr[lchild] : pArr[rchild];
int min_pos=pArr[lchild]<=pArr[rchild] ? lchild : rchild;
if(pArr[i]>pArr[min_pos]){
swap(pArr,i,min_pos);
next_pos=min_pos;
}
}
if(next_pos==-1) break;
lchild=next_pos*2+1;
rchild=next_pos*2+2;
}
}
}
//调整堆
void adjust(int *pArr,int var_size){
int pos=0;
while((pos*2+1)<var_size){
int next_pos=-1;
if((pos*2+2)>=var_size&&pArr[pos]>pArr[pos*2+1]){
swap(pArr,pos,pos*2+1);
next_pos=pos*2+1;
}
if((pos*2+2)<var_size){
int min_keys=pArr[pos*2+1]<=pArr[pos*2+2] ? pArr[pos*2+1] : pArr[pos*2+2];
int min_pos=pArr[pos*2+1]<=pArr[pos*2+2] ? (pos*2+1) : (pos*2+2);
if(pArr[pos]>min_keys){
swap(pArr,pos,min_pos);
next_pos=min_pos;
}
}
if(next_pos==-1) break;
pos=next_pos;
}
}
void heap_sort(int *pArr,int size){
create(pArr,size);
int var_size=size;
while(var_size>0){
pArr[0]=pArr[var_size-1];
--var_size;
adjust(pArr,var_size);
}
}
/*************
* 归并排序 *
*************/
//合并
void merge(int *pArr, int *merged, int si, int mi, int ti){
//把已近排序号的si-mi,mi-ti两个序列赋值给raw
for(int t=si;t<=ti;t++)
pArr[t]=merged[t];
//归并
int i=si,j=mi+1,k=si;
for(;i<=mi&&j<=ti;){
if(pArr[i]<=pArr[j]) merged[k++]=pArr[i++];
else merged[k++]=pArr[j++];
}
if(i<=mi)
for(int x=i;x<=mi;)
merged[k++]=pArr[x++];
if(j<=ti)
for(int y=j;y<=ti;)
merged[k++]=pArr[y++];
}
//划分
void partition(int *pArr, int *merged, int s, int t){
if(s==t) merged[s]=pArr[s];
else{
int m=(s+t)/2;
partition(pArr, merged, s, m);
partition(pArr, merged, m+1,t);
merge(pArr, merged, s,m,t);
}
}
void merge_sort(int *pArr,int size){
int * merged=(int *)malloc(size*sizeof(int));
partition(pArr,merged,0,size-1);
free(merged);
}
void main()
{
srand(unsigned(time(0)));
//每次产生一组数量递增的待排序列
for(int elementNum=MIN_ELEMENT_NUM;elementNum<=MAX_ELEMENT_NUM;elementNum+=INCREMENT_NUM){
int ctRun=0;
int avgNum;
for(avgNum=0;avgNum<1;avgNum++){
int *pArray = new int[elementNum]; //待排序列数组
fill_array(pArray,elementNum);
clock_t ctBegin = clock();
//straight_insertion_sort(pArray,elementNum); //直接插入排序
//binary_insertion_sort(pArray,elementNum); //折半插入排序
shell_sort(pArray,elementNum); //希尔排序
//bubble_sort(pArray,elementNum);//起泡排序
//quick_sort(pArray,elementNum); //快速排序
//simple_selection_sort(pArray,elementNum);//简单选择排序
//tree_selection_sort(pArray,elementNum); //树形选择排序
//heap_sort(pArray,elementNum);//堆排序
//merge_sort(pArray,elementNum); //归并排序
clock_t ctEnd = clock();
ctRun+=(ctEnd-ctBegin);
delete[] pArray;
}
ctRun/=avgNum;
cout<<"size="<<elementNum<<" avg time="<<ctRun<<"ms"<<endl;
}
}
分享到:
相关推荐
【排序结构5】基于比较的内部排序总结 在计算机科学中,排序是将一组数据按照特定顺序排列的过程。内部排序,或称为内存排序,是指数据记录在内存中进行的排序,与外部排序(数据量太大无法全部装入内存)相对。本...
本篇内容主要总结了多种内部排序算法,包括它们的特点、效率以及适用场景。 1. 选择排序(Selection Sort):不稳定排序,平均时间复杂度为O(n^2)。它通过反复遍历待排序的数据,每次找到最小(或最大)的元素,...
### 数据结构课程设计:内部排序算法比较_C语言 #### 一、课题背景与意义 排序作为数据结构中的重要组成部分,在实际开发中具有广泛的应用场景。理解不同排序算法的特点及其适用场景,对于提高程序效率和解决问题...
**内部排序算法比较** 在计算机科学中,内部排序是指数据在内存中进行的排序过程,无需额外的存储设备。本报告主要关注了六种常见的内部排序算法:起泡排序、直接插入排序、简单选择排序、快速排序、希尔排序和堆...
本文将详细探讨一款基于C++开发的内部排序图形化界面,该界面采用Microsoft Foundation Classes (MFC)库构建,实现了包括冒泡法、快速排序在内的六种常见排序算法,并提供了实时查看排序过程的功能,为学习和理解...
根据给定的信息,本文将对数据结构中的内部排序算法进行详细的分析与比较。这些排序算法在计算机科学领域占据着极其重要的地位,它们不仅被广泛应用于实际问题解决之中,还为理解算法复杂度提供了很好的示例。 ### ...
总结来说,这个课程设计是关于理解、比较和评估内部排序算法的实践项目,旨在提升学生的算法分析能力和解决问题的能力,为未来的软件开发工作打下坚实基础。通过这样的学习,学生不仅能掌握各种排序算法,还能了解到...
这篇实验报告主要探讨了内部排序算法在C++中的实现和比较,涉及的排序算法包括冒泡排序、直接插入排序、简单选择排序、快速排序以及希尔排序。这些算法都是经典的内部排序方法,它们在不同的场景下有不同的性能表现...
总结来说,"内部排序法比较.rar"提供了学习和比较各种内部排序算法的资源,对于深入理解数据结构和算法,提升编程能力具有极大的价值。通过实践和分析,我们可以更好地掌握这些基本的排序方法,并在实际项目中做出...
根据给定文件的信息,本文将对五种内部排序算法(插入排序、冒泡排序、简单选择排序、快速排序以及归并排序)进行性能比较,并简要介绍这些算法的基本原理及其实现过程。以下是对每种排序算法的具体分析: ### 一、...
总结来说,理解和掌握这些内部排序算法对于开发高效且优化的MFC应用程序至关重要。在实际编程中,了解不同算法的特性可以帮助我们做出明智的选择,提高程序的执行效率。通过深入学习和比较这些排序算法,不仅可以...
rt(int x[], int n) { ...这些内部排序算法各有特点,适用于不同的场景。例如,快速排序在大多数情况下效率高,而归并排序则保证了稳定性。了解这些算法有助于在实际编程中根据具体情况选择合适的排序方法。
总结来说,"内部排序算法的实现与比较"这一主题是软件开发人员的基础技能,它涉及到一系列经典的排序算法,每个都有其独特的特点和适用范围。通过深入学习和实践,学生可以提高问题解决能力,为未来的编程生涯打下...
### 堆排序总结 #### 1. 堆排序定义 堆排序是一种基于比较的排序算法,它利用了一种特殊的完全二叉树结构——堆(heap)来组织数据。在一个堆中,每个节点的关键字都不大于(对于大根堆)或都不小于(对于小根堆)...
根据给定的文件信息,我们可以深入探讨数据结构中的内部排序算法以及其实现方式。内部排序是在计算机内存中完成的排序过程,与外部排序相比,它处理的数据量相对较小,但效率通常更高。以下是对文件中提及的几种排序...
《内部排序算法详解》 内部排序是计算机科学中数据处理的重要组成部分,主要涉及如何高效地对内存中的数据进行排列。本课程设计旨在深入探讨各种内部排序算法,通过提供的"internal_sort.rar"压缩包,我们可以看到...
Hoare在1960年提出,是目前最常用的内部排序算法之一。快速排序的核心思想是分治法:选取一个基准元素,将数组划分为两部分,一部分的元素都小于基准,另一部分的元素都大于基准,然后对这两部分分别进行快速排序。...
总结来说,内部排序是编程和数据分析的基础,理解和掌握各种排序算法的原理和特性,有助于我们更好地解决实际问题,提高程序运行效率。通过学习和实践,我们可以灵活运用这些算法,以应对不同的数据处理需求。
根据给定的文件信息,我们可以总结出以下关于“内部排序:堆排序与快速排序”的相关知识点: ## 一、快速排序算法(Quick Sort) ### 1. 快速排序的基本概念 快速排序是一种高效的排序算法,由英国计算机科学家C.A...