基本排序算法的浅析与实现(c++)
来源:互联网 发布:mac根据路径查找文件 编辑:程序博客网 时间:2024/05/22 04:25
好久没写了,最近恰好有时间,就把简单的排序算法实现一遍,复习一下吧。
1. 插入排序
基本思想:假设有a1,a2,a3,a4;且a4前面的a1
void insert_sort(int a[],int l){ int i,j,temp; for(i=1;i<l;i++) { temp=a[i]; for(j=i-1;j>=0&&temp<a[j];j--) { a[j+1]=a[j];//temp小于一次就往后挪一位 } a[j+1]=temp;//此时temp正好不小于a[j],则temp找到了该放的位置 }}完整代码:#include<iostream>using namespace std;void insert_sort(int a[],int l){ int i,j,temp; for(i=1;i<l;i++) { temp=a[i]; for(j=i-1;j>=0&&temp<a[j];j--) { a[j+1]=a[j];//temp小于一次就往后挪一位 } a[j+1]=temp;//此时temp正好不小于a[j],则temp找到了该放的位置 }}print_arr(int b[],int length){ for(int k=0;k<length;k++) { cout<<b[k]; } } int main(){ int array[]={2,4,1,9,3,8,7,5,6,10,9}; int len=sizeof(array)/sizeof(0); print_arr(array,len); cout<<endl; insert_sort(array,len); print_arr(array,len); return 0;}
- shell排序
基本思想:shell排序是在直接插入排序的基础上建立的一种排序算法,插入排序在要排序的元素极多时效率极差,假设要对a10000排序,则它最坏情况下必须和前面的10000个数进行比较,前挪10000次;此时效率是极差的。而shell排序的改进之处在于使用一个分量如1000,先把10000个数分成10组,每组在进行插入排序,这样比较和挪动的次数为原来的1/10,
然后在减小分量为100,此时10000个数被分成100组,对这100组再进行插入排序。再减小分量,重复之 ,知道分量为1,此时在进行插入排序,与直接插入排序算法不同的是,此时的大部分元素都排好序,而且未排好序的元素需要插入的跨度不是很大,如a10000也许只需和a9999比较一次就可以插入了。
#include<iostream>using namespace std;void shell_sort(int a[],int l){ int i,j,temp; int h; for(h=l/2;h>=1;h=h/2)//处理分量,逐渐减小 注意这里h不能写成h>0,那样会变成死循环 { for(i=h;i<l;i=i+h)//这里就是插入排序 { temp=a[i]; for(j=i-h;j>=0&&temp<a[j];j=j-h)//如果有100个数排序的话,这里插入排序的对象就是a[0],a[50],a[100] { a[j+h]=a[j]; } a[j+h]=temp; } }}void print_arr(int b[],int length){ for(int k=0;k<length;k++) { cout<<b[k]; } cout<<endl;}int main(){ int array[]={7,3,1,2,4,5,9,8,10,6}; int len=sizeof(array)/sizeof(0); cout<<"shell排序前:\n"; print_arr(array,len); shell_sort(array,len); cout<<"shell排序后:\n"; print_arr(array,len); return 0;}
- 快速排序
主要思想:使用一个partition函数处理数组,此函数的作用是选出一个随机数,把数组中小于这个随机数的元素都放到此元素的左边,把数组中大于此元素的值都放到此元素的右边,再把这个元素放到该放的位置。Quick_sort()函数里面递归调用partition()函数。快速排序是不稳定的排序,最好时间复杂度为O(nlogn),最坏时间复杂度为O(n^2)。
#include<iostream>#include<time.h>using namespace std;int RandomInRange(int a,int b)//使用c++ rand()获取随机数必须结合srand(time(NULL)),rand()是依靠初始化值产生随机数{ if(b>a) { srand(time(NULL)); //而srand(time(NULL))初始化初始值,使每次产生的随机数不一样 return a+rand()%(b-a+1);//产生a~b之间的随机数 } }void swap(int *a,int *b)//交换 { int temp; temp=*a; *a=*b; *b=temp;}int partition(int data[],int length,int start,int end)//关键算法,使得元素按a1,a2,a3,a4...small...an-2,an-1,an排列,返回small的位置small大于之前的元素,小于之后的元素 { if(data==NULL||length<=0||start<0||end>length) { cout<<"输入错误!"<<endl; } int index=RandomInRange(start,end);//产生随机数 swap(&data[index],&data[end]); int small=start-1; for(int i=start;i<end;i++) { if(data[i]<data[end]) { ++small; if(small!=i)//i走到small前面的时候,i>small,需要交换,使得small依次排列 { swap(&data[i],&data[small]); } } } ++small; swap(&data[small],&data[end]); return small;}void quick_sort(int data[],int length,int start,int end)//递归排序 { if(start==end)//递归结束条件 { return; } int index=partition(data,length,start,end); if(index>start) { quick_sort(data,length,start,index-1); } if(index<end) { quick_sort(data,length,index+1,end); } }print_arr(int b[],int len)//打印 { for(int k=0;k<len;k++) { cout<<b[k]; } cout<<endl;}int main(){ int array[]={2,3,1,4,5,10,9,7,8,6}; int len=sizeof(array)/sizeof(array[0]); int start=0; int end=start+len-1; cout<<"快速排序前的元素为:"<<endl; print_arr(array,len); quick_sort(array,10,0,9); cout<<"快速排序后的元素为:"<<endl; print_arr(array,len); return 0;}
四.选择排序
基本思想:先假设第一个元素有序,然后把2到n-1个元素依次和第一个元素比较,如果小于第一个元素则交换之,此时第一个元素已经排好序了,然后在排第二个元素,把3到n-1个元素和第二个元素比较,如果小于则交换之。个人感觉这种方法比较笨,时间复杂度为O(n^2),但是比较稳定。
#include<iostream>using namespace std;void swap(int &a,int &b){ a=a^b; b=b^a; a=a^b;}void select_sort(int a[],int l){ for(int i=0;i<l;i++) { int temp=a[i]; for(int j=i+1;j<l;j++) { if(a[j]<temp) swap(a[j],temp); } a[i]=temp; } } void print_arr(int array[],int length) { for(int k=0;k<length;k++) { cout<<array[k]; } cout<<endl; }int main(){ int array[]={6,4,2,3,1,11,7,8,5,10,9}; int len=sizeof(array)/sizeof(array[0]); cout<<"选择排序前的元素:\n"; print_arr(array,len); select_sort(array,len); cout<<"选择排序后的元素:\n"; print_arr(array,len); return 0; }
五.冒泡排序
相邻的两个数比较,如a[j+1]
#include<iostream>using namespace std;void swap(int &a,int &b){ a=a^b; b=b^a; a=a^b;}void bubble_sort(int a[],int l){ for(int i=0;i<l;i++) { for(int j=0;j<l;j++) { if(a[j+1]<a[j]) { swap(a[j+1],a[j]); } } }}print_arr(int b[],int length){ for(int k=0;k<length;k++) { cout<<b[k]; } cout<<endl; }int main(){ int array[]={2,1,3,5,4,6,8,7,9,10}; int len=sizeof(array)/sizeof(array[0]); cout<<"冒泡排序前的元素:\n"; print_arr(array,len); bubble_sort(array,len); cout<<"冒泡排序后的元素为:\n"; print_arr(array,len); return 0;}
6.归并排序
主要思想:对于一个给定序列进行归并排序,借助一个数组temp[],先把这个序列递归地分成两两一组(二路归并),比较之,小的结果存放在temp[]中,再递归回到上一层,再比较。也许这样说你还是不懂,那就别看上面的,来看下面这个图。结合代码来看这个图更容易理解。
#include<iostream>#define N 100using namespace std;typedef int DataType;//合并data[begin...mid]和data[mid+1.end]到temp[begin,end]中,然后复制到data[begin,end]中void merge(DataType *data,DataType *temp,int begin,int mid,int end){ int i,j,k; for(i = begin,j=mid+1,k = begin;i<=mid&&j<=end;k++) { if(data[i]<=data[j]) temp[k] = data[i++]; else temp[k] = data[j++]; } if(i<=mid) while(i<=mid) temp[k++] = data[i++]; else while(j<=end) temp[k++] = data[j++]; for(i=begin;i<=end;i++) data[i] = temp[i];}//归并排序void Msort(DataType *data,DataType *temp,int begin,int end){ if(begin==end) data[begin] = data[begin]; else { int mid = (begin+end)/2; Msort(data,temp,begin,mid); Msort(data,temp,mid+1,end); merge(data,temp,begin,mid,end); }}print_arr(DataType arr[],DataType len){ for(int k=0;k<len;k++) { cout<<arr[k]; } cout<<endl;}int main(){ //data存储原数据和排序后的数据,temp为辅助数据 DataType data[N],temp[N]; int n; cout<<"请输入元素个数:"; cin>>n; int i; cout<<"请输入待排序的元素:"<<endl; for(i=0;i<n;i++) cin>>data[i]; cout<<"归并排序前的元素:"<<endl; print_arr(data,n); Msort(data,temp,0,n-1); cout<<"归并排序后的元素:"<<endl; print_arr(data,n);system("pause");return 0;}
7.关于对的理解和堆排序
关于队的理解这篇博客写的很详细:http://blog.csdn.net/morewindows/article/details/6709644/
我总结关于堆主要有以下几点需要注意:
1. 一般都用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。
2. 结点插入,插入结点的时先把瑶插入的结点插入到堆的最下面(数组最后一个元素),然后就是一个向上调整的过程,涉及函数是MinHeapFixup()。
3. 结点删除,结点删除时,规定总是删除堆顶元素,所以删除a[0],然后把最后一个元素放到a[0],后面就是一个向下的调整过程,对应的函数MinHeapFixdown()。
例如要把数组a[]={9,12,17,30,50,20,60,65,4,49},堆化,从第一个非叶子结点向下调整。
#include<iostream>using namespace std;swap(int *a,int *b){ *a=*a^*b; *b=*b^*a; *a=*a^*b;}//建立堆结点 //新加入i结点,其父结点为(i-1)/2//插入一个结点,总是先把他放到最后,所以他是一个向上调整的过程void MinHeapFixup(int a[],int i) { int j,temp; temp=a[i]; j=(i-1)/2; //父结点 while(j>=0&&i!=0) { if(a[j]<temp) //如果父结点小于当前结点,则此节点不用调整 break; a[i]=a[j]; //父结点大于当前结点,把父结点和当前结点交换 i=j; //更新当前结点的位置 j=(i-1)/2; //更新当前结点的父结点的位置 } a[i]=temp; } void MinHeapAddNumber(int a[],int n,int nNum) { a[n]=nNum; //插入一个结点,先把他放到最后,然后再向上调整 MinHeapFixup(a,n); } //删除堆结点 // 从i节点开始调整,n为节点总数 从0开始计算 i节点的子节点为 2*i+1, 2*i+2 //堆的删除总是删除a[0],然后把最偶一个结点放到a[0],最后就向下调整就行了 void MinHeapFixdown(int a[],int i,int n) { int j,temp; temp=a[i]; j=2*i+1; while(j<n) { if(j+1<n&&a[j+1]<a[j]) //再左右孩子中找到最小的 j++; if(a[j]>temp) break; a[i]=a[j]; //向下调整 i=j; j=2*i+1; } a[i]=temp; } void MinHeapDeleteNumber(int a[],int n) { swap(a[0],a[n-1]); //删除第一个元素 ,把最后一个元素放到第一个元素的位置 MinHeapFixdown(a,0,n-1); //向下调整 } //建立最小堆void MakeMinHeap(int a[],int n) //a[]数组已经是模拟好的堆, { for(int i=n/2-1;i>=0;i--) //从第一个非叶子结点开始向下调整 { MinHeapFixdown(a,i,n); } } //堆排序void heap_sort(int a[],int len){ for(int i=len-1;i>=1;i--) { swap(a[i],a[0]); MinHeapFixdown(a,0,i); } } print_arr(int a[],int len){ for(int i=0;i<len;i++) { cout<<a[i]<<','; } cout<<endl;}int main(){ int array[]={9,12,17,30,50,20,60,65,4,49}; int len=sizeof(array)/sizeof(array[0]); cout<<"堆排序前的元素是:"<<endl; print_arr(array,len); MakeMinHeap(array,len); heap_sort(array,len); cout<<"堆排序后的元素是:"<<endl; print_arr(array,len); return 0; }
- 基本排序算法的浅析与实现(c++)
- 基本排序算法的C语言实现
- 基本排序算法的C语言实现
- 基本排序算法的实现代码(c++)
- 几个基本排序算法的代码实现(C语言)
- 基本的排序算法原理与实现
- 插入排序算法浅析与JAVA实现
- 浅析数据结构与算法2--基本排序算法
- 各种基本的排序算法在Object-C实现
- 基本排序算法的实现
- 基本排序算法的实现
- 几个基本排序算法总结( C语言实现 )
- 总结八大排序算法的基本思想与代码实现
- 浅析数据结构与算法6--符号表及其基本实现
- 基本排序算法总结(C/C++)
- 《数据结构与算法》-单链表基本操作的C语言实现
- 算法与数据结构-堆的基本操作C语言实现
- 算法与数据结构-队列的基本操作C语言实现
- openCV—Python(1)——初始化环境
- 关于视频播放的问题呢
- 【Android归纳】Activity生命周期-基于实验的最新总结
- Online Judge System For SzNOI 题库 语法百题 c++ d037
- 7.23计划
- 基本排序算法的浅析与实现(c++)
- Hackerrank-Data structures-Tree
- Online Judge system For SzNOI 题库 语法百题 c++ d038
- 杭电ACM2665——Kth number~~划分树
- Android Recovery OTA升级(一)—— make otapackage
- HDU 2063 BNUOJ 6207 过山车 (最大流or二分匹配)
- hdu5289 Assignment(多校第一场第二题:RMQ+找规律或单调队列+找规律)
- 贪心算法之区间调度问题
- HDU 3709 Balanced Number (数位DP)