六种排序算法总结

参考资料:

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所指向的动态数组











  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值