`
liuxinglanyue
  • 浏览: 547818 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

基于比较的内部排序总结

阅读更多

转自:爪哇人

 

#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】 基于比较的内部排序总结

    NULL 博文链接:https://hxraid.iteye.com/blog/646760

    基于C++实现的各种内部排序算法汇总

    这里就把各种内部排序算法总结归纳了一下,包括插入排序(直接插入排序,折半插入排序,希尔排序)、交换排序(冒泡排序,快速排序)、选择排序(简单选择排序,堆排序)、2-路归并排序。(另:至于堆排序算法,前面...

    各种排序算法的比较与分析

     快速排序是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短;  堆排序所需的辅助空间少于快速排序,并且不会出现快速排序可能出现的最坏情况。这两种排序都...

    最新Hadoop的面试题总结

    ReduceTask工作机制 (1)Copy阶段:ReduceTask从各个MapTask上远程...保证输出的每个文件内部排序。 (2)全排序: 如何用Hadoop产生一个全局排序的文件?最简单的方法是使用一个分区。但该方法在处理大型文件时效率极

    Golang 实现插入排序的方法示例(2种)

    总结其与冒泡、选择的区别在于,内部迭代的次数是逐渐增大的,二后两者随着排序进行迭代次数逐渐减少 尝试基于Go的实现: 插入排序都采用in-place在数组上实现。具体算法描述如下: 从第一个元素开始,该元素可以...

    OpenCV 找圆算法((HoughCircles)总结与优化代码

    Opencv内部提供了一个基于Hough变换理论的找圆算法,HoughCircle与一般的拟合圆算法比起来,各有优势:优势:HoughCircle对噪声点不怎么敏感,并且可以在同一个图中找出多个圆;反观拟合圆算法,单纯的拟合结果容易...

    java 面试题 总结

    从内存方面来看, Stateful Session Bean 与 Stateless Session Bean 比较, Stateful Session Bean 会消耗 J2EE Server 较多的内存,然而 Stateful Session Bean 的优势却在于他可以维持使用者的状态。 9、...

    基于区间分析的建设项目经济评估方法比较 (2008年)

    为解决项目建设中的不确定性经济评估问题,对区间净现值(INPV)法、区间动态投资回收期(IPT )法及区间内部收益率(IIRR)法等3种项目经济评估方法进行了比较。给出了各区间评估方法的基本概念和评估准则,总结了其优缺点;...

    Java语言基础下载

    内部类 106 实例分析 110 抽象类,接口 115 内容总结 120 独立实践 121 第八章:异常 122 学习目标 122 异常的概念 123 异常的分类 123 实例分析 124 自定义异常 126 方法覆盖和异常 127 内容总结 129 第九章:基于...

    【Java设计模式】你对单例模式了解多少,一文深入探究

    目录单例模式懒汉式单例模式未初始化问题解决Double Check 双重检查方案一:不让第二步和第三步重排序-DoubleCheck方案二:基于类初始化-静态内部类饿汉式饿汉式与懒汉式最大区别序列化破坏单例模式原理枚举单例基于...

    ASP.NET4高级程序设计第4版 带目录PDF 分卷压缩包 part1

    15.2.5 公开内部Web控件 15.3 动态加载用户控件 15.4 局部页面缓存 15.4.1 VaryByControl 15.4.2 共享缓存控件 15.5 总结 第16章 主题和母版页 16.1 层叠样式表 16.1.1 创建样式表 16.1.2 应用...

    freemarker总结

    方法变量通常是基于给出的参数计算值在数据模型中定义。 6、 用户自定义FTL指令:宏和变换器 7、 节点 节点变量表示为树型结构中的一个节点,通常在XML处理中使用。 在模板里对sequences和hashes初始化 ...

    21天学通Java-由浅入深

    ”:非运算符 54 3.4.4 逻辑运算符总结 54 3.5 三元运算符 55 3.6 位运算符 55 3.6.1 “&”:按位与运算符 56 3.6.2 “|”:按位或运算符 56 3.6.3 “^”:按位异或运算符 57 3.7 位移运算符 57 3.7.1 “&gt;&gt;”:带...

    传智播客扫地僧视频讲义源码

    06_学员学习标准_排序及问题抛出 07_数组做函数参数退化问题剖析_传智扫地僧 08_数据类型基础提高 09_数据类型引申和思考 10_变量本质剖析和内存四区模型引出_传智扫地僧 11_c的学习重理解到位_对初学者_传智扫地僧 ...

    ASP.NET4高级程序设计(第4版) 3/3

    15.2.5 公开内部Web控件 530 15.3 动态加载用户控件 531 15.4 局部页面缓存 534 15.4.1 VaryByControl 535 15.4.2 共享缓存控件 536 15.5 总结 537 第16章 主题和母版页 538 16.1 层叠样式表 538 ...

    3D游戏卷2:动画与高级实时渲染技术——2

    6.2.4 物体内部分辨率变化 6.2.5 对称性/可逆性 6.2.6 局部简化操作 6.3 排序(误差)标准 6.3.1 排序标准——外观相似 6.3.2 排序标准——局部体积不变 6.3.3 排序标准——二次误差度量 6.3.4 排序标准——简化外壳 ...

    3D游戏卷2:动画与高级实时渲染技术——1

    6.2.4 物体内部分辨率变化 6.2.5 对称性/可逆性 6.2.6 局部简化操作 6.3 排序(误差)标准 6.3.1 排序标准——外观相似 6.3.2 排序标准——局部体积不变 6.3.3 排序标准——二次误差度量 6.3.4 排序标准——简化外壳 ...

    asp.net知识库

    可按任意字段排序的分页存储过程(不用临时表的方法,不看全文会后悔) 常用sql存储过程集锦 存储过程中实现类似split功能(charindex) 通过查询系统表得到纵向的表结构 将数据库表中的数据生成Insert脚本的存储过程!!! ...

    java面试常见基础(深层次,高级研发)

    3.2. 内部集成构建服务器案例 15 4. 常量池在jvm的哪个空间里边? 17 5. jvm垃圾回收是什么时候触发的? 17 5.1. 那究竟GC为我们做了什么操作呢? 17 5.1.1. Jvm怎么判断对象可以回收了? 18 5.2. 下面我们来看一下...

Global site tag (gtag.js) - Google Analytics