七种常见排序

几种排序,写了忘,忘了写,写的时候总是不能一气呵成,不知道别人是怎么一下子写出来的,是背下来,还是理解之后再写,感觉理解之后写还是很慢,怀疑自己是不是很笨。

今天又写了一遍。

#include<iostream>
using namespace std;

void bubble_sort(int *s, int n);
void bubble_sort2(int *s, int n);
void Slect_sort(int *s, int n);
void quick_sort(int *s, int left, int right);
void shell_sort(int *s, int n);
void insert_sort(int *s, int n);
void merge_sort(int *s, int n);
void heap_sort(int *s, int n);

int main()
{
	int n = 10;
	int a[] = {3,4,2,6,9,0,1,8,7,5};
	heap_sort(a, n);
//	insert_sort(a, 10);
//	quick_sort(a, 0, 9);
//	bubble_sort(a, n);
//	Slect_sort(a, 10);
//	merge_sort(a, 10);
//	shell_sort(a, 10);
	for (int i = 0; i < n; i++) {
		cout << a[i];
	}
	getchar();
	return 0;
}

/*
 *   冒泡排序
 */
void bubble_sort(int *s, int n)
{
	for (int i = 0; i < n-1; i++)
		for (int j = 0; j < n-1-i; j++) 
			if (s[j] > s[j+1]) 
				swap(s[j], s[j+1]);
}
/*
 *   像插入排序,又像交换排序,不知道是什
 *   么排序,反正挺简洁的,但是效率不行
 */
void bubble_sort2(int *s, int n)
{
	for (int i = 0; i < n; i++)
		for (int j = 0; j< i; j++)
			if(s[i] < s[j])
				swap(s[i], s[j]);
}

/*
 *        选择排序
 */
void Slect_sort(int *s, int n)
{
	for(int i=0; i<n; i++) {
		int pos = i;
		for(int j=i+1; j<n; j++)
			if(s[j] < s[pos])
				pos = j;
		swap(s[i], s[pos]);
	}
}


/*
 *   快速排序
 *
 *   对挖坑填数进行总结
 *   1.i =L; j = R; 将基准数挖出形成第一个坑a[i]。
 *   2.j--由后向前找比它小的数,找到后挖出此数填前一个坑a[i]中后i++。
 *   3.i++由前向后找比它大的数,找到后也挖出此数填到前一个坑a[j]中后j--。
 *   4.再重复执行2,3二步,直到i==j,将基准数填入a[i]中。
 *   http://blog.csdn.net/morewindows/article/details/6684558
 */
void quick_sort(int *s, int left, int right)
{
	if (left < right) {
		int i = left, j = right, x = s[left];
		while (i < j) {
			while (i < j && s[j] >= x)          /* 从后往前比较,跳过比 x 大(或等于)的数,找到比 x 小的数*/
				j--;
			if (i < j)
				s[i++] = s[j];

			while (i < j && s[i] < x)           /* 从后往前比较,跳过比 x 小的数,找到比 x 大(或等于)的数*/
				i++;
			if (i < j)
				s[j--] = s[i];
		}
		s[i] = x;
		quick_sort(s, left, i-1);
		quick_sort(s, i+1, right);
	}
}

/*
 *    插入 排序     v1
 *    方法原理还是“填坑”
 *    每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。 
 *   第一趟比较前两个数,然后把第二个数按大小插入到有序表中; 第二趟把第三个数据与
 *	  前两个数从后向前扫描,把第三个数按大小插入到有序表中;依次进行下去,进行了
 *	  (n-1)趟扫描以后就完成了整个排序过程。
 *
 */

void insert_sort(int *s, int n)
{
	for (int i = 1; i < n; i++) {
			int temp = s[i];
			int j;
			for (j = i; j >= 1 && temp < s[j-1]; j--)
				s[j] = s[j-1];
			s[j] = temp;
	}
}

/*
 *    shell 排序  v1
 */
/*
void shell_sort(int *s, int n)
{
	int gap;
	for(gap = n/2; gap>=1; gap /= 2) {           //gap = 组数        分成gap 个组
		for(int i=0; i<gap; i++) {               // 逐一对每一组采用插入排序
			for(int j=i+gap; j<n; j += gap) {    // 从每一组的第二个元素开始
				int temp = s[j];
				int k;
				for(k=j; k>=gap && temp < s[k-gap]; k -= gap)
					s[k] = s[k-gap];
				s[k] = temp;
			}
		}
	}
}
*/

/*
 *    shell 排序  v2
 */
void shell_sort(int *s, int n)
{
	int gap, i;
	for(gap = n/2; gap>=1; gap /=2) {
		for(i = gap; i < n; i++) {       // 每一元素在各自组内 采用插入排序
			int temp = s[i];             // 比 shell_sort v1 清晰
			int j;         
			for(j = i; j>=gap && temp < s[j-gap]; j -= gap) 
				s[j] = s[j-gap];
			s[j] = temp;
		}
	}
}

/*
 *    归并排序
 */
void merge_arry(int *s, int left, int mid, int right, int *temp)
{
	int i = left, j = mid+1;
	int k = 0;
	while(i <= mid && j <= right) {
		if(s[i] <= s[j])                  //   s[i]>s[j] ? temp[k++]=s[j++] : temp[k++]=s[i++]
			temp[k++] = s[i++];
		else
			temp[k++] = s[j++];
	}
	while(i <= mid)
		temp[k++] = s[i++];
	while(j <= right)
		temp[k++] = s[j++];
	for(i=0; i<k; i++)
		s[left+i] = temp[i];
}
void Merge_Sort(int *s, int left, int right, int *temp)
{
	if(left<right) {
		int mid = (left+right)/2; 
		Merge_Sort(s, left, mid, temp);              //  左边排序
		Merge_Sort(s, mid+1, right, temp);           //  右边排序
		merge_arry(s, left, mid, right, temp);       //  合并两有序序列到 temp[]中
	}
}
void merge_sort(int *s, int n)
{
	int *p = new int[n];
	Merge_Sort(s, 0, n-1, p);
	delete[] p;
}


/*
 *    堆排序
 *    建堆是从数组中最后一个非叶子节点开始的,每一次都会将较大的放在上层节点
 *    维护堆是从根节点开始的,其实也可以像建堆一样从最后一个非叶子节点开始,
 *    但是没必要,因为swap(  )之后除了根节点其它的都满足堆的性质,即根节点
 *    a[0]之后未排好序的节点都是上层节点比子节点大的,因此从a[0]开始就行了
 */

void heapify(int a[], int i, int n)     //   a 是待比较数组,i 是 (子)堆的顶点, n 是待堆化(子)数组大小
{
	int left = 2*i+1;
	int right = 2*i+2;
	int large_pos = i;
	if(left<n && a[left] > a[large_pos])
		large_pos = left;
	if(right<n && a[right] > a[large_pos])
		large_pos = right;
	if(large_pos != i) {
		swap(a[i], a[large_pos]);       //  只有交换之后才会破坏堆的性质,
		heapify(a, large_pos, n);       //  第 i 和 第large_pos 交换了,这
	}                                   //  这破坏了以下标large_pos 为顶点的堆的性质,所以将继续将它堆化
}
void build_heap(int a[], int n)     //建堆
{
	for(int i=n/2-1; i>=0; i--)
		heapify(a, i, n);          //堆化
}

void heap_sort(int a[], int n)
{
	build_heap(a, n);
	for(int i=n-1; i>=1; i--) {
		swap(a[0], a[i]);
		heapify(a, 0, i);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值