参考资料:
1.《MoreWindows 白话经典算法之七大排序(第2 版)》
2. http://blog.csdn.net/jnu_simba/article/details/9705111
一、冒泡排序(BubbleSort)
注意:用gcc编译c++程序要加-lstdc++.
eg. gcc -lstdc++ -o sort sort.cpp
这样,可以再循环语句中对循环变量赋值。
void swap1(int *left, int *right){ //形参为指针类型
//交换left和right所指向变量的值
int temp=*left;
*left=*right;
*right=*temp;
}
void swap2(int &left,int &right){ //函数的参数为引用类型。引用类型的形参与相应的实参占用相同的内存空间,也就是说,改变形参值,实参会随着变化
<span style="white-space:pre"> </span>//交换两个int型变量的值
<span style="white-space:pre"> </span>int temp=left;
<span style="white-space:pre"> </span>left=right;
<span style="white-space:pre"> </span>right=temp;
}
//swap3和swap2一样,形参都是引用类型
void swap3(int &left,int &right){
if (left !=right){ //注意:若left和right引用的是同一个变量,那么会将这个变量置为0。所以排除这种情况
left ^=right;
right ^=left;
left ^=right;
}
}
swap1, swap2, swap3 都是交换两个变量的值。
对数组而言,swap1实参为 &a[1], swap2, swap3实参为a[1].
基本的冒泡排序算法:
void BubbleSort1(int a[],int n){
for (int i=1;i<n;i++){ //执行n-1趟,i从1取到n-1,每次执行完将arr[i-1]的值就位
for (int j=n-1;j>=i;j--){ 反向检测,第i趟对arr[n-1]~arr[i]起泡
if (a[j-1]>a[j]) swap1(&a[j-1],&a[j]);
}
}
}
其中swap1的作用可以用下面的交换代替:
int temp=arr[j-1];
arr[j-1]=arr[j];
arr[j]=temp;
改进的冒泡排序算法:
//思路:在算法中增设一个标志exchange,用以标记本趟起泡排序是否发生了逆序和交换,没有则exchange=false,表示已经全部排好序,因而可以终止处理,结束算法。
void BubbleSort2(int a[],int n){
for (int i=1;i<n;i++){
bool change=false;
for (int j=n-1;j>=i;j--){
if (a[j-1]>a[j]){
change=true;
swap1(&a[j-1],&a[j]);
}
}
if (change==false) return;
}
}
二、直接插入排序(Insert Sort)
直接插入排序的算法:
void InsertSort1(int a[],int n){
for (int i=1;i<n;i++){ //为a[i]在前面的a[0,……,i-1]区域找到合适的位置
int j;
for (j=i-1;j>=0;j--)
if (a[j]<=a[i]) break; //找到了合适的位置,a[i]应在j+1位置
if (j!=i-1){ //将原来的j+1~i-1依次向后移动一个
int temp=a[i];
for (int k=i-1;k>j;k--) a[k+1]=a[k];
a[j+1]=temp;
}
}
}
改进的直接插入排序算法:
//思路:一边将a[j]向后移动一边搜索a[i]的插入位置
void InsertSort2(int a[],int n){
for (int i=1;i<n;i++){
if (a[i-1]>a[i]){
int temp=a[i];
int j;
for (j=i-1;j>=0&&a[j]>a[i];j--) //检查a[0,……,n-1]
a[j+1]=a[j];
a[j+1]=temp;
}
}
}
三、希尔排序(Shell Sort / Diminishing-increment sort)
按定义严格来写的希尔排序
void ShellSort1(int a[],int n){
<span style="white-space:pre"> </span>for (int gap=n/2;gap>0;gap /=2) //步长设定
for (int i=0;i<gap;i++) //按组排序
for (int j=i+gap;j<n;j+=gap) //组内采用直接插入排序
if(a[j]<a[j-gap]){
int temp=a[j];
int k;
for(k=j-gap;k>=i&&a[k]>temp;k-=gap) a[k+gap]=a[k];
[k+gap]=temp;
}
}
四、直接选择排序(Select Sort)
直接选择排序和直接插入排序都是将数据分为有序区和无序区;
其区别是——
直接插入排序:将无无序区的第一个元素插入到有序区形成一个更大的有序区;
直接选择排序:在无序区选择一个最小的元素放在有序区的最后面;
void SelectSort(int a[],int n){
for (int i=0;i<=n-2;i++){
int MinIndex=i; //找最小元素的位置
for (int j=i+1;j<n;j++)
if (a[j] <a[MinIndex]) MinIndex=j;
swap1(&a[i],&a[MinIndex]); //将找到的最小元素放到无序区的开头
}
}
五、快速排序(Quick Sort)
快速排序采用了分治(divide-and-conquer)的策略。
该方法的基本思想是:
1.先从数组找出一个数作为基准数;
2.AdjustArray——将大于等于这个数的全都放到它右边,小于它的数全都放到它左边;
3.再对左右左右区间重复第2步,直到各区间只剩下一个数。
(具体解说参见《大话数据结构》)
快速排序的代码:
int AdjustArray(int s[],int l,int r){
int i=l,j=r;
int x=s[l];
while(i<j){
while(i<j&&s[j]>=x) j--; //从右向左找小于x的数填坑
if (i<j){ s[i]=s[j]; i++;}
while(i<j&&s[i]<x) i++; //从左向右找大于等于x的数填坑
if (i<j){ s[j]=s[i];j--;}
}
s[i]=x;
return i; //返回调整后基准数的位置
}
//分治法的代码
void QuickSort(int s[],int l,int r){
if (l<r){
int i=AdjustArray(s,l,r);
QuickSort(s,l,i-1);
QuickSort(s,i+1,r);
}
}
六、归并排序(Merge Sort)
void merge(int a[],int tmp_array[],int lpos,int rpos,int rightn){
int leftn=rpos-1;
int tmpos=lpos;
int num_elements =rightn-lpos+1;
while(lpos<=leftn && rpos <=rightn)
if (a[lpos]<=a[rpos]) tmp_array[tmpos++]=a[lpos++];
else tmp_array[tmpos++]=a[rpos++];
while(lpos <=leftn) tmp_array[tmpos++]=a[lpos++]; //copy the rest of the left part
while(rpos <=rightn) tmp_array[tmpos++]=a[rpos++]; //copu the rest of the right part
for (int i=0;i<num_elements;i++,rightn--) a[rightn]=tmp_array[rightn]; //copy array back
}
void msort(int a[],int tmp_array[],int left,int right){
int center;
if(left<right){
center=(left+right)/2;
msort(a,tmp_array,left,center);
msort(a,tmp_array,center+1,right);
merge(a,tmp_array,left,center+1,right);
}
}
void MergeSort(int a[],int n){
int *tmp_array =(int *)malloc(n*sizeof(int)); //创建一个由n个int 型元素所构成的一维动态数组变量
if (tmp_array !=NULL){
msort(a,tmp_array,0,n-1);
free(tmp_array);
}
else printf("No space for tmp_array!\n");
}
函数malloc在stdlib.h 中声明:
eg:
int *p;
p=(int *)malloc(sizeof(int)); //创建一个int 型动态变量
int *q=(int *)malloc(sizeof(int)*n); //创建一个有n个int型元素所构成的一维动态数组变量
用malloc生成的动态变量,用free使之消除。
free(p); //撤销p所指向的动态变量
free(q); //撤销q所指向的动态数组