您的位置:首页 > 理论基础 > 数据结构算法

C++数据结构 排序 二分 插入 冒泡 基数 归并 直选 快排 希尔 堆排序

2011-06-28 00:27 591 查看
原文地址:http://hi.baidu.com/sunguangran/blog/item/f972073465c0b347241f1425.html

认真的学习了严蔚敏版的数据结构,感觉应该自己实现一下通用的算法才能有更深入的理解,于是贡献给大家下面这些我自己写的,使用C++模版实现了所有常见的排序算法,所有算法都很短小精悍,gcc编译运行通过(希尔排序除外)。
其中快速排序的代码最短小实用(欢迎各位dx拍砖),last监视哨的思想来自百度百科对qsort的解释----它大大简化了qsort的代码量。后续我将测试所有这些算法性能的情况,并对比C/C++库的标准函数。

(1)2分法查找有序连续内存

template <class C>
int bsearch(C value,iterator begin,iterator end){
iterator mid=& begin[(end-begin)/2];
if(*mid==value)return begin-mid;
else{
if(begin==end)return -1;
if(value<*mid)return bsearch(value,begin,mid);
else          return bsearch(value,++mid,end);
}
return -1;
}
int main(void){
int buf2[]={1,3,9,10};
int idx=bsearch<int,int*>(1,buf2,&buf2[3]);
if(idx!=-1)printf("v=%d,pos=%d/n",buf2[idx],idx);
else printf("not found/n");
return 0;
}

(2)插入排序(稳定)----当然,可以用折半插入排序来提高性能
template <class T>
void isort(T begin,size_t length){
size_t l=length*sizeof(*begin);
T      s=(T)malloc(l);
s[0]=begin[0];
for(int b=1;b<length;++b){
size_t c=0;
for(;c<b;++c){
if(begin[b]<s[c]){
for(size_t k=b-c;k>0;--k){
s[c+k]=s[c+k-1];
}
break;
}
}
s[c]=begin[b];
}
memcpy(begin,s,l);
delete[] s;
}
main(...)
short buf2[]={11,3,9,10,7,6,15,2};
isort(buf2,8);
for(int i=0;i<sizeof(buf2)/sizeof(short);++i)printf("%d ",buf2[i]);


(3)冒泡排序(稳定)
template <class T>
void bubsort(T s,size_t len){
for(int i=0;i<len-1;++i){//loop count
int op=0;
for(int m=0;m<len-i;++m){
if(s[m]>s[m+1]){
int tmp=s[m];
s[m]=s[m+1];
s[m+1]=tmp;
op=1;
}
}
if(!op)return;
}
}


(4)基数排序:O(nlog(r)m)其中r为所采取的基数,而logr(n)=m为堆数,在某些时候,基数排序法的效率高于其它的比较性排序法。合理设计r和m的值,可以得到最有解。它利用了每次比较以后得到的历史信息。需要根据需求具体设计,没有通用形式,必须根据具体问题的信息具体设计,例如扑克牌排序等。它的核心思想是利用数据的某方面的特定信息。下面的例子是排序如果各2位正数,使用了10个桶

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<iterator>
#include<iostream>
//Radix,Bucket sort
#define DEMICAL 10
int buk[DEMICAL][DEMICAL+1];//bucket
short t[DEMICAL];//top;
int *p;
void getb(size_t b){
printf("/nt[b]=%d,",t[b]);
if(t[b]==0){
printf("buk[%d] is empty",b);
return;
}else{
for(int i=1;i<=t[b];++i){
printf("buk[%d,%d]=%d ",b,i,buk[b][i]);
*p++=buk[b][i];
}
}
}
void getall(){for(int a=0;a<DEMICAL;++a){getb(a);} printf("/n");}
int main(int argc, char *argv[])
{
int pi[]={34,23,53,66,73,81,13,22,5,98,92,2,35,6,78,81,51,20,63,55,31,61,90,27,77};
int l=sizeof(pi)/sizeof(int);
#define PUSH(b,v) buk[b][++t[b]]=v
for(size_t i=0;i<l;++i){//low demical
int hvb=pi[i]%10;
PUSH(hvb,pi[i]);
}
p=pi;
getall();
copy(&pi[0],&pi[l],ostream_iterator<int>(cout," "));
printf("/n");
for(int st=0;st<DEMICAL;++st){t[st]=0;}
for(size_t i=0;i<l;++i){//high demical
int hvb=pi[i]/10;
PUSH(hvb,pi[i]);
}
p=pi;
getall();
copy(&pi[0],&pi[l],ostream_iterator<int>(cout," "));
printf("/n");
return 0;
}


(5)归并排序
template <class T>
void merge(T* begin,T* end,size_t len){
int es=sizeof(*begin);//元素大小
int ss=1;//sub size;//组内元素个数
while(ss<len){
int gs=ss<<1;
int group=len/gs+len%gs;//分组个数
if(gs>group)group=1;
printf("gsize=%d,group=%d,ss=%d===========/n",gs,group,ss);
for(int i=0;i<group;++i){
T* left=&begin[i*gs];
T* mid =&begin[i*gs+gs];
if(i==group-1)mid=end;//always process end element
mergesort<T*>(left,mid,end);//由于两部分已经有序,因此可以使用mergeList方法来实现合并
}
ss<<=1;
}
}
归并的递归实现
void merge(T* begin,T*end){
int* mid=(int*)( ( (int)begin+(int)end )/2 );
if(begin!=mid)merge(begin,mid);
if(mid!=end) merge(++mid,end);
mergesort<T*>(begin,mid,end);//实现方法同上
}


(6)直接选择排序(不稳定)

/*用法
int buf[]={7,3,5,2,4,9,3,12,1,6};
csort(buf,&buf[10]);
*/
template <class T>
void csort(T* begin,T* end){
for(T* b=begin;b!=end;++b){
T* n=b;
++n;
bool op=false;
while(n!=end){
T v=*b;
if(*n<v){
*n^=*b;
*b^=*n;
*n^=*b;
op=true;
}
++n;
}
if(op==false)return;
}
}


(7)快速排序(不稳定)----如果您的实现比我的更简短,欢迎对比:)

/*用法
int buf[]={17,3,15,2,4,9,3,12,1,6};
qsort(&buf[0],&buf[10]);
copy(&buf[0],&buf[10],ostream_iterator<int>(cout," "));
*/
#define swap(x,y) (x)^=(y);(y)^=(x);(x)^=(y)
template <class T>
void qsort(T begin,T end){
T left=begin;
if(++left>=end)return;//只有一个元素了
size_t m= ( (size_t)end-(size_t)begin )/(2*sizeof(T));//STL里面这个中间位置是怎么计算的? int*并没有distace和advance这样对应的迭代方法... ...
T mid=&begin[m];
swap(*begin,*mid);
T last=left;
for(;left!=end;++left){
if(*begin>*left){//找到了更小的数
if(left!=last){
swap(*left,*last);
}
++last;
}
}
qsort(begin,last);
qsort(last,end);
}


(8)希尔排序(不稳定)
可以理解为直接插入排序的变体。这里只给出伪代码:
首先实现一个直接插入排序
void isort(*begin,size_t offset,size_t number);
这里offset是插入排序的间隔,number是插入排序的元素个数
void shellsort(T begin,T end,size_t s){
for(int g=sqr(s);g>1;g=sqr(g)){//分组
size_t gs=s/g;//gs 是 group size
for(int n=0;n<gs;++n){//每次分组以后,处理某个组里面全部的元素
isort(begin+n*g, g, g);
}//每个组的所有元素
if(gs*g<s)isort(begin+gs*g,g,s-gs*g);//末尾剩余的元素
}//若干个组
}

(9)最后隆重推出百万级俱乐部成员: 堆排序。程序模板在gcc3.4.2下验证通过
#include<cstdio>
#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<iterator>
using namespace std;
#define swap(x,y) (x)^=(y);(y)^=(x);(x)^=(y)
template <class T>
void hadjust(T heap,size_t len){
size_t sub=len/2;//不大于n/2的整数
while(sub){
size_t left =sub<<1;
size_t right=left+1;
int csub;//需要交换的子节点
if(right>len)csub=left;
else csub=heap[left-1]>heap[right-1]?left:right;
if(heap[sub-1]>=heap[csub-1]){
--sub;
continue;
}
swap(heap[sub-1],heap[csub-1]);
--sub;
}
}
template <class T>
void hsort(T heap,size_t s){
while(s>1){
hadjust<T>(heap,s);
swap(heap[0],heap[s-1]);
--s;
}
}
int main(void){
int buf[]={17,3,15,2,4,9,3,12,1,6,8,12};
hsort(buf,12);
copy(&buf[0],&buf[12],ostream_iterator<int>(cout," "));
system("PAUSE");
return 0;
}


// HeapSortTest.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include<iterator>

using namespace std;

#define swap(x,y) (x)^=(y);(y)^=(x);(x)^=(y)

template <class T>
void hadjust(T heap,size_t len)
{
size_t sub=len/2;//不大于n/2的整数

while(sub)
{
size_t left =sub<<1;
size_t right=left+1;
int csub;//需要交换的子节点
if(right>len)
csub=left;
else
csub=heap[left-1]>heap[right-1]?left:right;

if(heap[sub-1]>=heap[csub-1])
{
--sub;
continue;
}

swap(heap[sub-1],heap[csub-1]);
--sub;
}
}

template <class T>
void hsort(T heap,size_t s)
{
while(s>1)
{
hadjust<T>(heap,s);
swap(heap[0],heap[s-1]);
--s;
}
}

int _tmain(int argc, _TCHAR* argv[])
{
// 	int buf[]={17,3,15,2,4,9,3,12,1,6,8,12};
int buf[]={40,55,49,73,12,27,98,81,64,36};
hsort(buf,10);
copy(&buf[0],&buf[10],ostream_iterator<int>(cout," "));
cout<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐