七种排序算法的分析和C语言源代码的实现

七种排序算法分析和C源代码的实现

选择排序

首先初始化数组首元素,外循环依次遍历排序数组,内循环再遍历数组,直至尾元素,若遇到需要交换的元素则进行交换,待双循环遍历结束,得到已排序好的数组。
时间复杂度:O(n2)
最坏情况:O(n2)
最好情况:O(n2)
稳定性:稳定
适用于n较小时

#include <stdio.h>
#define MAX 50000

int n, a[MAX], t;

int main()
{
	scanf("%d", &n);
	for(int i=1; i<=n; i++)
		scanf("%d", &a[i]);
	for(int i=1; i<n; i++)
	{
		for(int j=i+1; j<=n; j++)
		{
			if (a[i] > a[j]) {
				t = a[i];
				a[i] = a[j];
				a[j] = t;
			}
		}
	} 
	for(int i=1; i<=n; i++)
		printf("%d ", a[i]);
	return 0;
}

冒泡排序

依次比较相邻两元素,若前一元素大于后一元素则交换之,直至最后一个元素即为最大;然后重新从首元素开始重复同样的操作,直至倒数第二个元素即为次大元素;待循环结束得到已排序好的集合。
时间复杂度:O(n2)
最坏情况:O(n2)
最好情况:O(n)
稳定性:稳定
适用于n较小时

#include <stdio.h>
#define MAX 1000001 

int a[MAX], n, t;

int main()
{
	scanf("%d", &n);
	for(int i=0; i<n; i++)
		scanf("%d", &a[i]);
	for(int i=0; i<n; i++)
	{
		for(int j=0; j<n-i-1; j++)
		{
			if(a[j] > a[j+1]) {
				t=a[j]; a[j]=a[j+1]; a[j+1]=t;	
			}
		}
	}
	for(int i=0; i<n; i++)
		printf("%d ", a[i]);
	return 0;
}

插入排序

数列前面部分看为有序,依次将后面的无序数列元素插入到前面的有序数列中,初始状态有序数列仅有一个元素,即首元素。在将无序数列元素插入有序数列的过程中,采用了逆序遍历有序数列,相较于顺序遍历会稍显繁琐,但当数列本身已近排序状态效率会更高。
时间复杂度:O(n2)
最坏情况:O(n2)
最好情况:O(n)
稳定性:稳定
适用于n较小时

#include <stdio.h>
#define MAX 100001

int n, a[MAX], t, j;

int main()
{
	scanf("%d", &n);
	for(int i=1; i<=n; i++)
		scanf("%d", &a[i]);
	for(int i=1; i<=n; i++)
	{
		t = a[i];
		for(j=i-1; j>=1; j--)
		{
			if (t < a[j]) {
				a[j+1] = a[j];
			}
			else break;
		}
		a[j+1] = t;
	}
	for(int i=1; i<=n; i++)
		printf("%d ", a[i]);
	return 0;
}

希尔排序

插入排序的改进版。为了减少数据的移动次数,在初始序列较大时取较大的步长,通常取序列长度的一半,此时只有两个元素比较,交换一次;之后步长依次减半直至步长为1,即为插入排序,由于此时序列已接近有序,故插入元素时数据移动的次数会相对较少,效率得到了提高。
时间复杂度:O(n3/2)
最坏情况:O(n2)
最好情况:O(n)
稳定性:不稳定

#include <stdio.h>
#define MAX 500000

int n, a[MAX], t;

int main()
{
	int t, k;
	scanf("%d", &n);
	for(int i=0; i<n; i++)
		scanf("%d", &a[i]);
	for(int i=n/2; i>0; i/=2)
	{
		for(int j=i; j<n; j++)
		{
			k = j;
			t = a[j];
			if (a[k] < a[k-i]) {
				while (k-i>=0&&t < a[k-i]) {
					a[k] = a[k-i];
					k -= i;
				}
				a[k] = t;
			}
		}
	}
	for(int i=0; i<n; i++)
		printf("%d ", a[i]);
	return 0;
}

桶排序(基数排序)

桶排序不是基于比较的排序算法,其核心在于将输入的数据值转化为键存储在额外开辟的数组空间(桶)中。作为一种线性时间复杂度的排序,桶排序要求输入的数据必须是有确定范围的整数。
时间复杂度:O(d(r+n))
最坏情况:O(d(r+n))
最好情况:O(d(r+rd))
稳定性:稳定

#include <stdio.h>
#define MAX 100000 

int a[MAX]={0}, n, t;

int main()
{
	scanf("%d", &n);
	for(int i=1; i<=n; i++)
	{
		scanf("%d", &t);
		a[t]++;
	}
	for(int i=0; i<=10000; i++)
		for(int j=1; j<=a[i]; j++)
			printf("%d ", i);
	return 0;
}

快速排序

选一基准元素,依次将剩余元素中小于该基准元素的值放置其左侧,大于等于该基准元素的值放置其右侧;然后,递归其左右两侧的集合进行相同的操作,快速排序是排序算法运用最广的算法。
时间复杂度:O(nlog2n)
最坏情况:O(n2)
最好情况:O(nlog2n)
稳定性:不稳定
适用于n较大时

#include <stdio.h>

int n, a[100001], k;

void qs(int l, int r)
{
	int i, j, t, temp;
	if (l > r) return ;
	
	temp = a[l];
	i = l;
	j = r;
	while (i != j)
	{
		while(a[j] <= temp && i<j)
		j--;
		while(a[i] >= temp && i<j)
		i++;
		if (i < j) {
			t = a[i];
			a[i] = a[j];
			a[j] = t;
		}	
	}
	a[l] = a[i];
	a[i] = temp;
	qs(l, i-1);
	qs(i+1, r);
}

int main()
{
	int i, j, t;
	scanf("%d", &n);
	for( i=1; i<=n; i++)
	scanf("%d", &a[i]);
	qs(1, n);
	for( i=1; i<=n; i++)
	printf("%d ", a[i]);	
	return 0;
}

堆排序

堆排序的思想借助于二叉堆中的最大堆得以实现。首先,将待排序数列抽象为二叉树,并构造出最大堆(或者最小堆);然后,依次将最大元素(即根节点元素)与待排序数列的最后一个元素交换(即二叉树最深层最右边的叶子结点元素);每次遍历,刷新最后一个元素的位置(自减1),直至其与首元素相交,即完成排序。
时间复杂度:O(nlog2n)
最坏情况:O(nlog2n)
最好情况:O(nlog2n)
稳定性:不稳定
适用于n较大时

#include <stdio.h>
#define MAX 500000 

int s[MAX], n, num, k;

void swap(int x, int y)
{
	int t;
	t = s[x]; s[x] = s[y]; s[y] = t;
} 

void shiftdown(int x)
{
	int t, book = 0;
	while (x*2 <= n&&book == 0) {
		if (s[x] > s[x*2]) {
			t = x*2;
		}
		else t = x;
		if (x*2+1 <= n) {
			if (s[x*2+1] < s[t]) {
				t = x*2+1;
			}
		}
		if (x != t) {
			swap(x, t);
			x = t;
		}
		else book = 1;
	}
}

void create()
{
	for(int i=n/2; i>=1; i--)
	{
		shiftdown(i);
	}
}

void heapsort()
{
	while(n > 0) {
		swap(1, n);
		n--;
		shiftdown(1);
	}
}

int main()
{
	scanf("%d", &num);
	n = num;
	for(int i=1; i<=n; i++)
	scanf("%d", &s[i]);
	create();
	heapsort();
	for(int i=num; i>0; i--)
	printf("%d ", s[i]);
	return 0;
}

感谢Jamest博主的参考博客链接

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值