c/c++排序算法-插入排序

排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。

直接插入排序(Straight Insertion Sort)

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

void printfarr(int *buf, int len,int count)
{
	if (buf == NULL)
	{
		return;
	}
	printf("%d:",count);
	int i = 0;
	for (i = 0;i < len;i++)
	{
		printf("%d ", buf[i]);
	}
	printf("\n");
}


void InsertSort1(int *arr, int n)
{
	int i = 0;
	for(i = 1;i < n;i++)
	{
		if(arr[i] < arr[i - 1])
		{
			int j = i - 1;
			int x = arr[i];	//定义一个哨兵,保存待排序的元素
			while(x < arr[j] && j >= 0)
			{
				arr[j + 1] = arr[j];
				j--;  			//元素后移
			}
			arr[j + 1] = x;		//插入到正确位置
		}
		printfarr(arr,n,i);
	}
}

void InsertSort2(int *array,unsigned int n)
{
    int i,j;
    int temp;
    for(i=1;i<n;i++)
    {
        temp=*(array+i);
        for(j=i;j>0&&*(array+j-1)>temp;j--)
        {
            *(array+j)=*(array+j-1);
        }
        *(array+j)=temp;
        printfarr(array,n,i);
    }
}

int main()
{
	int a[9] = {3,1,5,7,2,4,9,6,8};
	InsertSort1(a,9);
	printfarr(a,9,9);
	return 0;
}
运行结果:
1:1 3 5 7 2 4 9 6 8 
2:1 3 5 7 2 4 9 6 8 
3:1 3 5 7 2 4 9 6 8 
4:1 2 3 5 7 4 9 6 8 
5:1 2 3 4 5 7 9 6 8 
6:1 2 3 4 5 7 9 6 8 
7:1 2 3 4 5 6 7 9 8 
8:1 2 3 4 5 6 7 8 9 
9:1 2 3 4 5 6 7 8 9 

real	0m0.002s
user	0m0.000s
sys		0m0.000s

基本思想:先将序列的第一个记录看成是一个有序的子序列,然后从第二个记录逐个进行插入,直至整个序列有序为止
重要要点:先定义个哨兵(临时变量)作为存储和判断数组边界之用

步骤描述:
一般来说,插入排序都采用in-place在数组上实现。具体算法描述如下:
⒈ 从第一个元素开始,该元素可以认为已经被排序
⒉ 取出下一个元素(监视哨),在已经排序的元素序列中从后向前扫描
⒊ 如果在已排序的元素中的一个元素大于新元素(监视哨),将该元素移到下一位置
⒋ 重复步骤3,直到找到已排序的元素小于或者等于新元素(监视哨)的位置
⒌ 将新元素(监视哨)插入到下一位置中
⒍ 重复步骤2~5
按照上述步骤可知,直接插入排序是稳定的排序方法

时间复杂度: T ( n ) = O ( n 2 ) T(n) = O(n^2) T(n)=O(n2)
空间复杂度: S ( n ) = O ( 1 ) S(n) = O(1) S(n)=O(1)

  • 若待排序记录按关键字从小到大情况下(正序)

关键字比较次数(最好情况下):
n − 1 n - 1 n1

记录移动次数(最好情况下):
∑ i = 0 n i = 0 \sum_{i=0}^n i = 0 i=0ni=0


关键字比较次数(最坏情况下)未经验证:
∑ i = 1 n i = 1 + 2 + 3 + 4 + 5 + . . . + n − 1 = n ( n − 1 ) 2 \sum_{i=1}^n i = 1+2+3+4+5+...+n-1 = \frac{n(n - 1)}{2} i=1ni=1+2+3+4+5+...+n1=2n(n1)

记录移动次数(最坏情况下)未经验证:
∑ i = 1 n i = 1 + 2 + 3 + 4 + 5 + . . . + n − 1 = n ( n − 1 ) 2 \sum_{i=1}^n i = 1+2+3+4+5+...+n-1 = \frac{n(n - 1)}{2} i=1ni=1+2+3+4+5+...+n1=2n(n1)

  • 若待排序记录按关键字随机情况下(取平均值)

关键字比较次数:
c o u n t = n 2 4 count = \frac{n^2}{4} count=4n2
记录移动次数:
c o u n t = n 2 4 count = \frac{n^2}{4} count=4n2

希尔排序(Shell Sort)

操作方法:
1.选择一个增量序列: t 1 , t 2 , t 3 , t 4 , t 5 , t k t_1,t_2,t_3,t_4,t_5,t_k t1t2t3t4t5tk,其中 t i &gt; t j , t k = 1 t_i &gt; t_j,t_k=1 ti>tj,tk=1
2.按增量序列个数k,对序列进行k趟排序
3.每趟排序,根据对应的增量 t i t_i ti,将待排序列分割成若干长度为m的子序列,分别对各子表进行直接插入排序。仅增量因子为1时,整个序列作为一个表来处理,表长度即为整个序列的长度

在这里插入图片描述

增量序列 d = { n 2 , n 4 , n 8 . . . 1 } n 为 要 排 序 的 个 数 d= \{\frac{n}{2},\frac{n}{4},\frac{n}{8}...1\} n为要排序的个数 d={2n,4n,8n...1}n
先将要排序的一组记录按某个增量 d   ( n 2 , n 为 要 排 序 数 的 个 数 ) d\ (\frac{n}{2},n为要排序数的个数) d (2n,n) 分成若干组子序列,每组中记录的下标相差d.对每组中全部元素进行直接插入排序,然后再用一个较小的增量 d 2 \frac{d}{2} 2d 对它进行分组,在每组中再进行直接插入排序。继续不断缩小增量直至为1,最后使用直接插入排序完成排序。它是不稳定的排序方法

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

void printfarr(int *buf, int len,int count)
{
    if (buf == NULL)
    {
        return;
    }
    printf("%d:",count);
    int i = 0;
    for (i = 0;i < len;i++)
    {
        printf("%d ", buf[i]);
    }
    printf("\n");
}

void ShellInsertSort(int *arr,unsigned int len,int dk)//直接插入排序
{
    int count = 0;
    for(int i = dk;i < len;i++)
    {
        if(arr[i] < arr[i - dk])    //若第i个元素大于i-1元素,直接插入,小于的话,移动有序表后插入
        {
            int j = i - dk;
            int temp = arr[i];       //复制为哨兵,即存储待排序元素
            while(temp < arr[j] && j >= 0)//查找在有序表的插入位置
            {
                arr[j + dk] = arr[j];
                j -= dk;//元素后移
            }
            count++;
            arr[j + dk] = temp;
            printfarr(arr, len,count);
        }
    }
    printf("the times of compare:%d\n",count);
}

void shellSort(int *arr,int len)
{
    int dk = len;
    do
    {
        dk = dk/2;
        ShellInsertSort(arr,len,dk);
    }while(dk > 1);
}

int main()
{
    //int a[9] = {3,1,5,7,2,4,9,6,8};
    int a[] = {49,38,65,97,76,13,27,48,55,4};
    shellSort(a,sizeof(a)/sizeof(int));
    return 0;
}
运行结果:
1:13 38 65 97 76 49 27 48 55 4
2:13 27 65 97 76 49 38 48 55 4
3:13 27 48 97 76 49 38 65 55 4
4:13 27 48 55 76 49 38 65 97 4
5:13 27 48 55 4 49 38 65 97 76
the times of compare:5
1:4 27 13 55 48 49 38 65 97 76
2:4 27 13 49 48 55 38 65 97 76
3:4 27 13 49 38 55 48 65 97 76
the times of compare:3
1:4 13 27 49 38 55 48 65 97 76
2:4 13 27 38 49 55 48 65 97 76
3:4 13 27 38 48 49 55 65 97 76
4:4 13 27 38 48 49 55 65 76 97
the times of compare:4

real	0m0.001s
user	0m0.000s
sys		0m0.000s

目前选取的增量是 d k = d k 2 dk = \frac{dk}{2} dk=2dk
大量的研究表明,当增量序列为以下公式时可以获得不错的效果 d l t a [ k ] = 2 t − k + 1 − 1   ( 0 ≤ k ≤ t ≤ log ⁡ 2 ( n + 1 ) ) dlta[k] = 2^{t-k+1}-1 \ ({0}\leq{k}\leq{t}\leq{\log_2{(n+1)}}) dlta[k]=2tk+11 (0ktlog2(n+1))
时间复杂度: O ( n 3 2 ) O(n^\frac{3}{2}) O(n23)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
美团餐馆预定信息的管理与分析涉及多个算法原理,以下是其中一些常用的算法原理: 1. 数据存储与管理:使用合适的数据结构来存储和管理餐馆和预定信息。常用的数据结构包括链表、数组、哈希表等。例如,可以使用链表或数组来存储餐馆信息和预定信息,使用哈希表来提高查询效率。 2. 排序算法:对预定信息进行排序可以方便后续的分析和查询。常用的排序算法有冒泡排序插入排序、选择排序、快速排序、归并排序等。根据实际需求和数据规模选择合适的排序算法。 3. 统计分析:对预定信息进行统计分析可以得到有关预定量、预定时间分布等的信息。常用的统计分析算法包括频率统计、累计统计、均值计算、方差计算等。 4. 查找算法:根据特定条件查找预定信息可以提供特定需求的查询功能。常用的查找算法有线性查找、二分查找、哈希查找等。选择合适的查找算法可以提高查询效率。 5. 数据挖掘与机器学习算法:对预定信息进行挖掘和建模可以得到更深入的分析结果。常用的数据挖掘和机器学习算法包括聚类算法、分类算法、回归算法等。根据实际需求选择合适的算法进行模型建立和分析。 以上仅是一些常用的算法原理示例,实际的算法原理与实现步骤可能因具体需求和数据特征而有所不同。在设计过程中,您需要综合考虑数据结构和算法原理,选择合适的方法来实现美团餐馆预定信息的管理与分析。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值