8.2 简单排序算法 (1) 插入排序 (2) 选择排序 (3) 冒泡排序 8.3 线性时间排序(1) 桶排序 (2) 计数排序 (3) 基数排序*(附代码)

8.2 简单排序算法

以下三种排序算法的时间复杂度是 O(n^2)。在这三种排序算法中,比较好的是插入排序。

(1) 插入排序!

基本思想:假设前 i 个元素已经排好序,然后把第 i+1 个元素插入到合适的位置上。

void ins_sort(int *a, int start, int end)
{
int j,k;
for (int i=start+1; i<end; i++)
{
for (k=a[i],j=i-1; k<a[j] && j>=start; j--)
a[j+1]=a[j];
a[j+1]=k;
}
}

(2) 选择排序!

基本思想:处理第 i 个元素时,找到它后面所有数的最小值。如果这个最小值比它小,就互相交换。

void swap_sort(int *a, int start, int end)
{
int temp;
for (int i=start; i<end; i++)
for (int j=i+1; j<end; j++)
if (a[i]>a[j])
temp=a[i],a[i]=a[j],a[j]=temp;
}

(3) 冒泡排序!
 

基本思想:对相邻两个元素进行比较,并将较小的数放到前面。重复 n 组即可完成排序。

void bubble_sort(int *a, int start, int end)
{
int temp;
for (int i=start; i<end; i++)
for (int j=end; j>i; j--) // 从start到i,在“冒泡”过程中,元素已经排好序。
if (a[j-1]>a[j])
temp=a[j-1], a[j-1]=a[j], a[j]=temp;
}

8.3 线性时间排序 

以下几种排序算法的时间复杂度为 O(n),因为它们使用的是基于数字本身的排序。

(1) 桶排序!

基本思想:设计 M 个桶,根据元素本身进行分配。因为 M 个桶是按顺序排列的,所以分配元素之后元素也会按顺序排列。
待排序的数据范围不太大时可以考虑这样排序(比如1~1000可以考虑,而1~100000就必须用快速排序)。
下面假设每个数都位于区间[1, M]。

int cnt[M];
memset(cnt,0,sizeof(cnt));
for (int i=0; i<N; i++)
cnt[a[i]]++;
// 从cnt[0]开始挨个列举就行了。例如
for (int i=0; i<M; i++)
while ((cnt[i]--)>0)
cout<<i<<" ";

(2) 计数排序

基本思想:对于序列中的每一元素 x,确定序列中小于 x 的元素的个数。下面假设每个数都位于区间[1, m]。

int a[N], b[N], cnt[M];
……
memset(cnt,0,sizeof(cnt));
for (int i=0;i<n;i++) cnt[a[i]]++;
for (int i=1;i<M;i++) cnt[i]+=cnt[i-1];
for (int i=n-1;i>0;i--)
{
b[cnt[a[i]]] = a[i];
cnt[a[i]]--;
}
// 输出结果
for (int i=0;i<n;i++) cout<<b[i]<<' ';

(3) 基数排序*

基本思想:对 n 个元素依次按 k,k-1,...1 位上的数字进行桶排序。

int tmp[N], cnt[10];
int n;
int maxbit(int *data, int n) // 辅助函数,求数据的最大位数
{
int d = 1; // 保存最大的位数
int p =10; 
for (int i = 0;i < n; i++) 
while (data[i] >= p) 
p *= 10, d++;
return d;
}
void radixsort(int *data, int n) // 基数排序
{ 
int d = maxbit(data,n); 
int i,j,k; 
int radix = 1; 
for (i = 1; i<= d;i++) // 进行d次排序
{ 
for (j = 0;j < 10;j++) 
cnt[j] = 0; // 每次分配前清空计数器
for (j = 0;j < n; j++) 
{ 
k = (data[j]/radix)%10; // 统计每个桶中的记录数
cnt[k]++; 
} 
for (j = 1;j < 10;j++) 
cnt[j] = cnt[j-1] + cnt[j]; // 将tmp中的位置依次分配给每个桶
for (j = n-1;j >= 0;j--) // 将所有桶中记录依次收集到tmp中
{
k = (data[j]/radix)%10;
cnt[k]--;
tmp[cnt[k]] = data[j];
}
for (j = 0;j < n;j++) // 将临时数组的内容复制到data中
data[j] = tmp[j]; 
radix = radix*10; 
}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值