排序算法

       在计算机编程中,排序算法作为比较常用的算法,在许多程序中都会用到,本篇会介绍一些常用的排序算法,以升序为例,比较研究不同排序算法的优劣,对于较慢的算法,仅给出冒泡排序为例,主要介绍几种速度较快的算法。

一、时间复杂度为o(n²)的排序

1、冒泡排序(稳定)

算法步骤:

(1)从待排序列第一个元素开始,前一个元素依次与后一个元素比较大小,若前者大,则二者交换,一次循环结束,可将最大元素放至待排序列的最后位置。

(2)一次循环后待排序列减少1,重复(1)过程直至序列有序。

执行代码如下:

#include
using namespace std;
void BubbleSort(int *b, int n);//冒泡排序 

int main()
{
	int *a, n, i;
	cin >> n;
	a = new int [n];
	for (i = 0;i < n;i++) //输入n个整数 
	{
		cin >> a[i];
	}
	BubbleSort(a, n);
	for(i = 0;i < n;i++)
	{
		cout << a[i] << ' ';
	}
        return 0;
}
void BubbleSort(int *b, int n)
{
	int i, j, t;
	for(i = 0;i < n;i++)// 每次循环可以把一个序列中最大的值换最后面 
	{				// 经过一次循环需要找最大值的序列长度减少1 
		for(j = 0;j < n-i-1;j++)  //n-i-1即为每次需要找最大值的序列长度 
		{
			if(b[j] > b[j+1])	  //每次从需要排序第一个元素开始,与相邻元素比较 
			{                 //前者大,则二者交换, 否则不变 
				t = b[j];
				b[j] = b[j+1];
				b[j+1] = t;
			}
		}
	}
}

二、时间复杂度为o(n*log2(n))的排序算法

1、快速排序(不稳定)

算法步骤:

(1)、将序列中的第一个元素单独拿出来。先从右往左找出第一个比该值小的元素并交换。

(2)、再从左往右找第一个比该值大的元素并交换。
(3)、交换完成后确保该值前面所有元素都比他小,后面所以元素比他大,从而从i将元素断开。
(4)、分别从下届到i-1和i+1到上届重复上述操作,直到下界和上届的值相等。

执行代码:

#include
using namespace std;
double Swap(double *x, double *y); 
void HoareSort(double *a, int n);
static void Hoare(double *a, int s, int n);//内部使用的递归函数 

int main()
{
	int n, i = 0;
	double *a;
	cin >> n;
	a = new double [n];
	while (i < n)
	{
		cin >> a[i++];
	}
	HoareSort(a, n);
	for(i = 0; i < n; i++)
	{
		cout << a[i] << ' ';
	}
        return 0;
}

double Swap(double *x, double *y)
{
	double t;
	t = *x;
	*x = *y;
	*y = t;
}
void HoareSort(double *a, int n)
{
	Hoare(a, 0, n-1);
}
void Hoare(double *a, int s, int n)
{
	int i = s,j = n;
	if(i < j)
	{
		while(i < j && a[j] > a[i])
		{
			--j;
		}
		Swap(&a[i], &a[j]);
		while(i < j && a[i] < a[j])
		{
			++i;
		}
		Swap(&a[i], &a[j]);
		Hoare(a, s, i-1);
		Hoare(a, i+1, n);	
	}
}

2、堆排序(不稳定)

算法分析:使用下筛法,利用二叉排序树,通过不断地调整堆,每次可以将最大值分离出来。

执行代码:

#include
using namespace std;

void HeapSort(double *a, int n);//堆排序 
static void HeapSift(double *a, int s, int n);//下筛法 
double Swap(double *x, double *y);

int main()
{
	int i = 0, n;
	double *a;
	cin >> n;
	a = new double [n];
	while (i < n)
	{
		cin >> a[i++];
	}
	HeapSort(a, n);
	for (i = 0; i < n; i++)
	{
		cout << a[i] << ' ';
	}
	return 0;
}
void HeapSort(double *a,int n)
{
	int k;
	for(k = n / 2 - 1; k >= 0; --k)
	{
		HeapSift(a, k, n - 1);//建初堆 
	}
	for(k = n - 1; k > 0; --k)
	{
		Swap(&a[0], &a[k]);//调整堆 
		HeapSift(a, 0, k-1);
	}
}
void HeapSift(double *a, int s, int m)//下筛从0开始的顺序表,完全二叉树,判断2*p+1<=m有左孩子 2*p+2<=m有右孩子 
{
	int p, k;//p用来表示父亲结点,每次需要下筛的值 k则用来计算左右孩子 
	double x;
	p = s;
	x = a[s]; //拷贝二叉树根结点的值 
	for (k = 2 * p + 1; k <= m; k = 2 * k + 1)//k从p的左孩子开始 到最后一个结点结束 每次循环结束k都为下一个左孩子 
	{
		if(k < m && a[k] < a[k+1])//判断p的右孩子存在,实际条件(k+1<=m) 并且左孩子小于右孩子,这时将k加1,使k为较大孩子下标 
		{
			++k;
		}
		if(x < a[k])//如果x的值比较大孩子的值小 
		{
			a[p] = a[k];//将较大孩子的值赋给父亲结点 
			p = k;     //同时该最大的孩子变为下一次循环的父亲结点 
		}
		else
		{
			k = m + 1; //k>m无左右孩子 跳出循环 
		}
	}
	a[p] = x;//将x赋值 
}

double Swap(double *x, double *y)
{
	double t;
	t = *x;
	*x = *y;
	*y = t;
}

 

你可能感兴趣的:(算法)