一些排序方法(堆排,归并,快排,计数排)

感觉学校算法课挺水的,不过编程这东西还是要靠自己想,自己琢磨,老师也只能帮你指引下。菜鸟我还是好好敲代码吧。。。。

计数排序:其他排序方法都是依靠元素之间的比较从而产生次序,而计数排序是依靠元素计算,得出自己在序列中的位置


//计数排序(设元素均为非负整数)
#include <iostream>
#include <memory.h>
using namespace std;

const int maxn = 50;
int Size = 8;

int a[maxn] = {2,5,3,0,2,3,0,3};
int b[maxn];//存储最后排列顺序
int c[maxn];//c[lp...rp],lp,rp应分别对应数组 最小和最大值,即lp <= min(a),rp >= max(a)
			//c[i]代表 <= i元素个数,即i在排序后的位置
void counting_sort()
{
	memset(c,0,sizeof(c));
	memset(b,-1,sizeof(b));

	for(int i = 0;i < Size;i++)
		c[a[i]]++;
	for(int i = 1;i < Size;i++)
		c[i] += c[i - 1];

	for(int i = 0;i < Size;i++)
	{
		b[c[a[i]]] = a[i];
		c[a[i]]--;
	}
}

int main()
{
	freopen("out.txt","w",stdout);
	counting_sort();
	for(int i = 0;i < maxn;i++)
		if(-1 != b[i])
			cout<<b[i]<<" ";
	return 0;
}

归并排序:使用分治的思想,将n个元素的序列分解为两个(n / 2 )大小的子序列(分解步奏),继续使用归并排序排列两个子序列(分治解决),最后将两个排序后的序列合并(关键步骤)

#include <iostream>
#include <math.h>
using namespace std;

const int maxn = 0x7fffffff;
const int size = 8;

int a[size] = {5,2,4,7,1,3,2,6};

void merge(int p,int q,int r)
{
	int n1 = q - p + 1;
	int n2 = r - q;

	int la[size],ra[size];
	for(int i = 1;i <= n1;i++)	//p ----- q
		la[i] = a[p + i - 1];
	for(int i = 1;i <= n2;i++)	//q + 1 ------ r
		ra[i] = a[q + i];

	la[n1 + 1] = maxn;
	ra[n2 + 1] = maxn;

	int i,j;
	i = j = 1;
	for(int k = p;k <= r;k++)
	{
		if(la[i] <= ra[j])
		{
			a[k] = la[i];
			i++;
		}
		else
		{
			a[k] = ra[j];
			j++;
		}
	}
}

void merge_sort(int p,int r)
{
	if(p < r)
	{
		int q = (p + r) / 2;
		merge_sort(p,q);
		merge_sort(q + 1,r);
		merge(p,q,r);
	}
}

int main()
{
	freopen("out.txt","w",stdout);
	merge_sort(0,7);
	for(int i = 0;i < size;i++)
		cout<<a[i]<<endl;
	return 0;
}

堆排序,大(小)顶堆可以近似的看成是一棵完全二叉树,除了最低层外,该树是全满的。所以很容易用一维数组存储完全二叉树。堆排中关键的地方在于维护好堆的性质,即a[parent(i)] >= a[i] (大顶堆) a[parent(i)] <= a[i] (小顶堆)

堆的一个重要的应用是构造优先队列,虽然STL中有了优先队列的模板,但了解其原理总没有什么坏处。


//大顶堆
#include <iostream>
#include <cstdio>
#include <cstdlib>

using namespace std;
const int maxn = 100;
int a[maxn] = {0,4,1,3,2,16,9,10,14,8,7};//从1开始存储
int Size = 10;//排序元素数量

void heapify(int num)//对下标num元素构造堆
{
	int largest = num;
	int lp = num * 2;
	int rp = lp + 1;

	if(lp <= Size && a[lp] > a[num])
		largest = lp;
	if(rp <= Size && a[rp] > a[largest])
		largest = rp;
	if(largest != num)
	{
		swap(a[num],a[largest]);
		heapify(largest);
	}
}


void build_heap()
{
	if(Size != 0)
	{
		for(int i = Size / 2;i >= 1;i--)
			heapify(i);
	}
}

void heap_sort()
{
	build_heap();
	for(int i = Size;i >= 1;i--)
	{
		cout<<a[1]<<" ";
		swap(a[1],a[Size]);
		Size--;
		heapify(1);
	}
}

int main()
{
	freopen("out.txt","w",stdout);
	heap_sort();
	return 0;
}

快速排序:快速排序也使用了分治的思想,序列a[p...r]被划分为两个子序列a[p...q-1] 和 a[p + 1....r],使得a[p...q - 1] <= a[q],a[q + 1...r]均大于a[q]。

#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
const int maxn = 50;

int a[maxn] = {2,8,7,1,3,5,6,4};
int Size = 8;

//两种划分方法,感觉后一种效率高些
/*
int partition(int p,int r)//以a[r]为基准元素比较
{
	int tmp = a[r];
	int i = p - 1;
	for(int j = p;j < r;j++)
	{
		if(a[j] < tmp)
		{
			i++;
			swap(a[i],a[j]);
		}
	}
	swap(a[i + 1],a[r]);
	return i + 1;
}
*/

int partition(int lp,int rp)
{
	int tmp = a[rp];
	while(lp < rp)
	{
		while(a[lp] <= tmp && lp < rp)
			lp++;
		a[rp] = a[lp];

		while(a[rp] >= tmp && lp < rp)
			rp--;
		a[lp] = a[rp];
	}
	a[lp] = tmp;
	return lp;
}

void quick_sort(int p,int r)
{
	if(p < r)
	{
		int pos = partition(p,r);
		quick_sort(p,pos - 1);
		quick_sort(pos + 1,r);
	}
}

int main()
{
	freopen("out.txt","w",stdout);
	quick_sort(0,7);
	for(int i = 0;i < Size;i++)
		cout<<a[i]<<" ";
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值