排序算法之线性排序(时间复杂度为线性)

桶排序

  • 桶排序的核心思想是将要排序的数据分到几个有序的桶里,每个桶里的数据再单独用快排或者冒泡等排序算法进行排序。桶内排完序之后,再把桶里的数据按照顺序依次取出,组成的序列就是有序的了。
  • 桶排序的时间复杂度是O(n)。我们分析一下,如果要排序的数据有n个,我们把它们均匀地划分到m个桶内,每个桶里就有k=n/m个元素。每个桶内部使用快速排序,时间复杂度为O(k * logk)。m个桶排序的时 间复杂度就是O(m * k * logk),因为k=n/m,所以整个桶排序的时间复杂度就是O(n*log(n/m))。当桶的个数m接近数据个数n时,log(n/m)就是一个非常小的常量,这个时候桶排序的时间复杂度接近O(n)。
  • 但是桶排序对要排序数据的要求非常苛刻的。首先,要排序的数据需要很容易就能划分成m个桶,并且,桶与桶之间有着天然的大小顺序。这样每个桶内的数据都排序完之后,桶与桶之间的数据不需要再进行排序。 其次,数据在各个桶之间的分布是比较均匀的。如果数据经过桶的划分之后,有些桶里的数据非常多,有些非常少,很不平均,那桶内数据排序的时间复杂度就 不是常量级了。在极端情况下,如果数据都被划分到一个桶里,那就退化为O(nlogn)的排序算法了。
  • 桶排序比较适合用在外部排序中。所谓的外部排序就是数据存储在外部磁盘中,数据量比较大,内存有限,无法将数据全部加载到内存中。
  • 当然可以对桶内的数据再进行一次划分,划分为更小的桶。

算法实现:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

int _tmain(int argc, _TCHAR* argv[]){
	int array_stu[50]={0};
	int array_out[100]={0};
    
    srand((int)time(NULL));//设置随机数的基准,这样保证每次的运行结果不同

    for(int i=0;i<50;i++)
    {
        array_stu[i] =(rand()%(99-1))+1;
    }

    /*把array_stu分别扔到对应的桶里面去
    里面的逻辑需要根据要求进行修改,这里是如果数值跟桶的编号一样,就把这个桶的数据增加
    */
    for(int i=0;i<50;i++)
    {
        for(int j=1;j<100;j++)
        {
            /*如果数值跟桶的编号一样,就把这个桶的数据增加*/
            if(array_stu[i] ==j)
            {
                array_out[j] ++;
            }
        }
    }
    
    /*把排序后的数据输出*/
    for(int i=0;i<100;i++)
    {
        while(array_out[i] > 0)
        {
            printf("%d\n",i);
            array_out[i]--;
        }
    }
	return 0;
}

计数排序

  • 当要排序的n个数据,所处的范围并不大的时候,比如最大值是k,我们就可以把数据划分为k个桶。每个桶内的数据值都是相同的,省掉了桶内排序的时间。
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
//计数排序
void CountSort(int *a, int len)
{
	//通过max和min计算出临时数组所需要开辟的空间大小
	int max = a[0], min = a[0];
	for (int i = 0; i < len; i++){
		if (a[i] > max)
			max = a[i];
		//if (a[i] < min)
		//	min = a[i];
	}
	//使用calloc将数组都初始化为0
//	int range = max - min + 1;
	int *b = (int *)calloc(max, sizeof(int));
	//使用临时数组记录原始数组中每个数的个数
	for (int i = 0; i < len; i++){
		//注意:这里在存储上要在原始数组数值上减去min才不会出现越界问题
		b[a[i]] += 1;
	}
	int j = 0;
	//根据统计结果,重新对元素进行回收
	for (int i = 0; i < max; i++){
		while (b[i]){
			//注意:要将i的值加上min才能还原到原始数据
			a[j++] = i ;
			b[i]--;
		}
	}
}
//打印数组
void PrintArray(int *a, int len)
{
	for (int i = 0; i < len; i++){
		printf("%d ", a[i]);
	}
	printf("\n");
}

int _tmain(int argc, _TCHAR* argv[]){
	int a[] = { 3, 4, 3, 2, 1, 2, 6, 5, 4, 7 };
	printf("排序前:");
	PrintArray(a, sizeof(a) / sizeof(int));
	CountSort(a, sizeof(a) / sizeof(int));
	printf("排序后:");
	PrintArray(a, sizeof(a) / sizeof(int));
	system("pause");
	return 0;
}
发布了60 篇原创文章 · 获赞 0 · 访问量 839

猜你喜欢

转载自blog.csdn.net/qq_36828822/article/details/104063691
今日推荐