数据排序的小汇总

2017马上就走啦。你好2018。

1.冒泡排序

冒泡排序的基本思想是:每次比较两个相邻的元素,如果它们的顺序错误就把它们交换过来。每次都是比较相邻的两个数,如果后面的数比前面的数大,则交换这两个数的位置。一直比较下去直到最后两个数比较完毕后,最小的数就在最后一个了。就如同是一个气泡,一步一步往后“翻滚”,直到最后一位。所以这个排序的方法有一个很好听的名字“冒泡排序”。

代码实现:
for (int i=1; i<=n-1; i++)
	for (int j=1; j<=n-i; j++)
		if (a[j]<a[j+1])
		{
			temp=a[j];
			a[j]=a[j+1];
			a[j+1]=temp;
		}

改进:设置一个布尔变量bo 来记录是否有进行交换。值为false表示本趟中进行了交换,true 则没有。代码如下:

int i=1;
do
{
	bo=true;
	for (int j=1; j<=n-i; j++)
		if (a[j]<a[j+1])
		{
			temp=a[j];
			a[j]=a[j+1];
			a[j+1]=temp;
			bo=false;
		}
	i++;
}
while (!bo);

冒泡排序的核心部分是双重嵌套循环。不难看出冒泡排序的时间复杂度是 O(N^2)。这是一个非常高的时间复杂度。冒泡排序早在 1956 年就有人开始研究,之后有很多人都尝试过对冒泡排序进行改进,但结果却令人失望。如 Donald E. Knuth(高德纳,1974 年图灵奖获得者)所说:“冒泡排序除了它迷人的名字和导致了某些有趣的理论问题这一事实之外,似乎没有什么值得推荐的。”

2.桶排序

桶排序的思想是若待排序的记录的关键字在一个明显有限范围内(整型)时,可设计有限个有序桶,每个桶装入一个值(当然也可以装入若干个值),顺序输出各桶的值,将得到有序的序列。

例:输入n个0到100之间的不相同整数,由小到大排序输出。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
	int b[101],k,i,n;
	memset(b,0,sizeof(b));                    //初始化
	scanf("%d",&n);
	for( i=1; i<=n; i++)
	{
		cin>>k;
		b[k]++;                //将关键字等于k的值全部装入第k桶
	}
	for( i=0; i<=100; i++)
		while (b[i]>0)
		{
			printf("%d  ",i);    //输出排序结果
			b[i]--;
		}
	printf("\n");
}
3.选择排序

基本思想:每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在待排序的数列的最前,直到全部待排序的数据元素排完。

过程模拟:

初始关键字[49 38 65 97 76 13 27 49]
第一趟排序后 13 [38 65 97 76 49 27 49]
第二趟排序后 13 27 [65 97 76 49 38 49]
第三趟排序后 13 27 38 [97 76 49 65 49]
第四趟排序后 13 27 38 49 [76 97 65 49]
第五趟排序后 13 27 38 49 49 [97 65 76]
第六趟排序后 13 27 38 49 49 65 [97 76]
第七趟排序后 13 27 38 49 49 65 76 [97]
最后排序结果 13 27 38 49 49 65 76 97 

代码实现:

void SelectSort(int R[])  		//对R[1..n]进行直接选择排序
{
	for(int i=1; i<=n-1; i++)                 //n - 1趟选择排序
	{
		K=i;
		for(int j=i+1; j<=n; j++)      //在当前无序区R[i..n]中选最小的元素R[K]
		{
			if(R[j]<R[K])  K=j;
		}
		if(K!=i)                                      //交换R[i]和R[K]
		{
			Temp=R[i];
			R[i]=R[K];
			R[K]=Temp;
		}
	}
}                                                           //SelectSort

4.插入排序

插入排序是一种简单的排序方法,其算法的基本思想是:

假设待排序的数据存放在数组R[1..n]中,增加一个哨兵结点x。

(1) R[1]自成1个有序区,无序区为R[2..n];
(2) 从i=2起直至i=n为止,将R[i]放在恰当的位置,使R[1..i]数据序列有序;

      ①  x:=R[i];

      ② 将x与前i-1个数比较, j:=i-1;  whilex<a[j] do j:=j-1;

      ③ 将R数组的元素从j位置开始向后移动: for k:=i downto j do a[k]:=a[k-1];

      ④ R[j]=x;

(3) 生成包含n个数据的有序区。

例如:设n=8,数组R中8个元素是: 36,25,48,12,65,43,20,58,执行插入排序程序后,其数据变动情况:

第0步:[36] 25 48 12 65 43 20 58
第1步:[25 36] 48 12 65 43 20 58
第2步:[25 36 48] 12 65 43 20 58
第3步:[12 25 36 48] 65 43 20 58
第4步:[12 25 36 48 65] 43 20 58
第5步:[12 25 36 43 48 65] 20 58
第6步:[12 20 25 36 43 48 65] 58
第7步:[12 20 25 36 43 48 58 65]

代码实现:

void insertsort(int r[])                  //对r[1..n]按递增序进行插入排序,x是监视哨
{
	for(i=2; i<=n; i++)                     //依次插入r[2],...,r[n]
	{
		x=r[i];
		j=i-1;
		while(x< r[j])                   //查找r[i]的插入位置//
		{
			r[j+1] =r[j];               //将大于r[i]的元素后移//
			j--;
		}
		r[j+1]=x;                       //插入r[I] //
	}
}

5.快速排序

快速排序是对冒泡排序的一种改进。它的基本思想是,通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

快速排序之所以比较快,是因为相比冒泡排序,每次交换是跳跃式的。每次排序的时候设置一个基准点,将小于等于基准点的数全部放到基准点的左边,将大于等于基准点的数全部放到基准点的右边。这样在每次交换的时候就不会像冒泡排序一样只能在相邻的数之间进行交换,交换的距离就大得多了。因此总的比较和交换次数就少了,速度自然就提高了。

代码看这里:http://blog.csdn.net/baidu_41248654/article/details/78698148

C++的STL(使用algorithm库中的sort函数):

#include<cstdio>
#include<algorithm>
int num[100010],n;
int main()
{
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
        scanf("%d",&num[i]);
    sort(num+1,num+n+1);
    for(int i=1; i<=n; i++)
        printf("%d ",num[i]);
    return 0;
}
6.归并排序

(来自http://blog.csdn.net/yuehailin/article/details/68961304

基本思路就是将数组分成二组A,B,如果这二组组内的数据都是有序的,那么就可以很方便的将这二组数据进行排序。如何让这二组组内数据有序?可以将A,B组各自再分成二组。依次类推,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的二个小组就可以了。这样通过先递归的分解数列,再合并数列就完成了归并排序。


//将有二个有序数列a[first...mid]和a[mid...last]合并。
void mergearray(int a[], int first, int mid, int last, int temp[])
{
	int i=first,j=mid+1;
	int m=mid,n=last;
	int k=0;

	while(i<=m&&j<=n)
	{
		if(a[i]<=a[j])
			temp[k++]=a[i++];
		else
			temp[k++]=a[j++];
	}
	while(i<=m)
		temp[k++]=a[i++];
	while(j<=n)
		temp[k++]=a[j++];
	for(i=0; i<k; i++)
		a[first+i]=temp[i];
}
void mergesort(int a[], int first, int last, int temp[])
{
	if (first<last)
	{
		int mid=(first+last) / 2;
		mergesort(a,first, mid, temp);    //左边有序
		mergesort(a,mid+1, last, temp); //右边有序
		mergearray(a,first, mid, last, temp); //再将二个有序数列合并
	}
}

bool MergeSort(int a[], int n)
{
	int *p=new int[n];
	if (p==NULL)
		return false;
	mergesort(a,0,n-1,p);
	delete[] p;
	return true;
}
7.小结


相关概念:
注:1、归并排序每次递归都要用到一个辅助表,长度与待排序的表长度相同,虽然递归次数是O(log2n),但每次递归都会释放掉所占的辅助空间,2、快速排序空间复杂度只是在通常情况下才为O(log2n),如果是最坏情况的话,很显然就要O(n)的空间了。当然,可以通过随机化选择pivot来将空间复杂度降低到O(log2n)。

1、时间复杂度

     时间复杂度可以认为是对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。

     常见的时间复杂度有:常数阶O(1),对数阶O(log2n),线性阶O(n), 线性对数阶O(nlog2n),平方阶O(n2)

     时间复杂度O(1):算法中语句执行次数为一个常数,则时间复杂度为O(1),

2、空间复杂度

    空间复杂度是指算法在计算机内执行时所需存储空间的度量,它也是问题规模n的函数

    空间复杂度O(1):当一个算法的空间复杂度为一个常量,即不随被处理数据量n的大小而改变时,可表示为O(1)

    空间复杂度O(log2N):当一个算法的空间复杂度与以2为底的n的对数成正比时,可表示为O(log2n)

                                ax=N,则x=logaN

    空间复杂度O(n):当一个算法的空间复杂度与n成线性比例关系时,可表示为0(n).


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值