第十六周项目1-(7)归并排序(8)基数排序

本文介绍了两种排序算法——堆排序和基数排序的C语言实现。堆排序通过不断调整堆来实现排序,基数排序则利用了关键字的位数特性来进行排序。文章提供了完整的代码示例并展示了排序过程。

问题及代码:

#include <stdio.h>
#define MaxSize 20
typedef int KeyType;    //定义关键字类型
typedef char InfoType[10];
typedef struct          //记录类型
{
    KeyType key;        //关键字项
    InfoType data;      //其他数据项,类型为InfoType
} RecType;              //排序的记录类型定义


//调整堆
void sift(RecType R[],int low,int high)
{
    int i=low,j=2*i;                        //R[j]是R[i]的左孩子
    RecType temp=R[i];
    while (j<=high)
    {
        if (j<high && R[j].key<R[j+1].key)  //若右孩子较大,把j指向右孩子
            j++;                                //变为2i+1
        if (temp.key<R[j].key)
        {
            R[i]=R[j];                          //将R[j]调整到双亲结点位置上
            i=j;                                //修改i和j值,以便继续向下筛选
            j=2*i;
        }
        else break;                             //筛选结束
    }
    R[i]=temp;                                  //被筛选结点的值放入最终位置
}


//堆排序
void HeapSort(RecType R[],int n)
{
    int i;
    RecType temp;
    for (i=n/2; i>=1; i--) //循环建立初始堆
        sift(R,i,n);
    for (i=n; i>=2; i--) //进行n-1次循环,完成推排序
    {
        temp=R[1];       //将第一个元素同当前区间内R[1]对换
        R[1]=R[i];
        R[i]=temp;
        sift(R,1,i-1);   //筛选R[1]结点,得到i-1个结点的堆
    }
}


int main()
{
    int i,n=10;
    RecType R[MaxSize];
   KeyType a[]= {57,40,38,11,13,34,48,75,6,19,9,7};
 for (i=1; i<=n; i++)
        R[i].key=a[i];
    printf("排序前:");
    for (i=1; i<=n; i++)
        printf("%d ",R[i].key);
    printf("\n");
    HeapSort(R,n);
    printf("排序后:");
    for (i=1; i<=n; i++)
        printf("%d ",R[i].key);
    printf("\n");
    return 0;
}

运行结果:


2)基数排序

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#define MAXE 20         //线性表中最多元素个数
#define MAXR 10         //基数的最大取值
#define MAXD 8          //关键字位数的最大取值
typedef struct node
{
    char data[MAXD];    //记录的关键字定义的字符串
    struct node *next;
} RecType;
void CreaLink(RecType *&p,char *a[],int n);
void DispLink(RecType *p);
void RadixSort(RecType *&p,int r,int d) //实现基数排序:*p为待排序序列链表指针,r为基数,d为关键字位数
{
    RecType *head[MAXR],*tail[MAXR],*t; //定义各链队的首尾指针
    int i,j,k;
    for (i=0; i<=d-1; i++)                  //从低位到高位循环
    {
        for (j=0; j<r; j++)                 //初始化各链队首、尾指针
            head[j]=tail[j]=NULL;
        while (p!=NULL)                 //对于原链表中每个结点循环
        {
            k=p->data[i]-'0';           //找第k个链队
            if (head[k]==NULL)          //进行分配
            {
                head[k]=p;
                tail[k]=p;
            }
            else
            {
                tail[k]->next=p;
                tail[k]=p;
            }
            p=p->next;                  //取下一个待排序的元素
        }
        p=NULL;                         //重新用p来收集所有结点
        for (j=0; j<r; j++)             //对于每一个链队循环
            if (head[j]!=NULL)          //进行收集
            {
                if (p==NULL)
                {
                    p=head[j];
                    t=tail[j];
                }
                else
                {
                    t->next=head[j];
                    t=tail[j];
                }
            }
        t->next=NULL;                   //最后一个结点的next域置NULL
        //以下的显示并非必要
        printf("  按%d位排序\t",i);
        DispLink(p);
    }
}
void CreateLink(RecType *&p,char a[MAXE][MAXD],int n)   //采用后插法产生链表
{
    int i;
    RecType *s,*t;
    for (i=0; i<n; i++)
    {
        s=(RecType *)malloc(sizeof(RecType));
        strcpy(s->data,a[i]);
        if (i==0)
        {
            p=s;
            t=s;
        }
        else
        {
            t->next=s;
            t=s;
        }
    }
    t->next=NULL;
}
void DispLink(RecType *p)   //输出链表
{
    while (p!=NULL)
    {
        printf("%c%c ",p->data[1],p->data[0]);
        p=p->next;
    }
    printf("\n");
}
int main()
{
    int n=10,r=10,d=2;
    int i,j,k;
    RecType *p;
    char a[MAXE][MAXD];
    int b[]={57,40,38,11,13,34,48,75,6,19,9,7};
    for (i=0; i<n; i++)     //将b[i]转换成字符串
    {
        k=b[i];
        for (j=0; j<d; j++) //例如b[0]=75,转换后a[0][0]='7',a[0][1]='5'
        {
            a[i][j]=k%10+'0';
            k=k/10;
        }
        a[i][j]='\0';
    }
    CreateLink(p,a,n);
    printf("\n");
    printf("  初始关键字\t");        //输出初始关键字序列
    DispLink(p);
    RadixSort(p,10,2);
    printf("  最终结果\t");         //输出最终结果
    DispLink(p);
    printf("\n");
    return 0;
}
运行结果:



内容概要:本文介绍了基于贝叶斯优化的CNN-LSTM混合神经网络在时间序列预测中的应用,并提供了完整的Matlab代码实现。该模型结合了卷积神经网络(CNN)在特征提取方面的优势与长短期记忆网络(LSTM)在处理时序依赖问题上的强大能力,形成一种高效的混合预测架构。通过贝叶斯优化算法自动调参,提升了模型的预测精度与泛化能力,适用于风电、光伏、负荷、交通流等多种复杂非线性系统的预测任务。文中还展示了模型训练流程、参数优化机制及实际预测效果分析,突出其在科研与工程应用中的实用性。; 适合人群:具备一定机器学习基基于贝叶斯优化CNN-LSTM混合神经网络预测(Matlab代码实现)础和Matlab编程经验的高校研究生、科研人员及从事预测建模的工程技术人员,尤其适合关注深度学习与智能优化算法结合应用的研究者。; 使用场景及目标:①解决各类时间序列预测问题,如能源出力预测、电力负荷预测、环境数据预测等;②学习如何将CNN-LSTM模型与贝叶斯优化相结合,提升模型性能;③掌握Matlab环境下深度学习模型搭建与超参数自动优化的技术路线。; 阅读建议:建议读者结合提供的Matlab代码进行实践操作,重点关注贝叶斯优化模块与混合神经网络结构的设计逻辑,通过调整数据集和参数加深对模型工作机制的理解,同时可将其框架迁移至其他预测场景中验证效果。
<think>嗯,用户想让我详细分析各种排序算法的原理和各趟排序过程。首先,我需要确定用户的基础水平,可能是学生或者刚学数据结构的人。他们需要清晰的步骤和例子,可能还不太明白这些排序之间的区别和应用场景。 首先,我得回忆每种排序的基本原理。比如直接插入排序是逐个插入到已排序序列,折半插入用二分法找位置,希尔排序是分组插入。冒泡和快速都属于交换排序,但快排用了分治。选择排序每次选最小,堆排序用堆结构。归并是分治合并,基数按位分配,计数则是统计频率。 用户可能需要每个排序的例子,所以得准备具体的数字序列,并一步步展示每趟的变化。比如用同一个例子,比如[8, 3, 5, 1, 2],但基数排序可能需要更多位数,比如三位数。或者调整例子以适应不同排序的需求。 需要注意各趟排序的细节,比如希尔排序的增量选择,堆排序的建堆和调整,归并的分割和合并过程。还要确保例子中的步骤准确,避免错误,比如快速排序的分区操作是否正确。 另外,用户可能希望对比这些排序的优缺点,虽然问题中没有明确要求,但详细分析各趟过程其实也间接展示了时间复杂度和稳定性。比如直接插入排序在部分有序时效率高,希尔排序通过分组提高效率,快速排序的平均性能好,但最坏情况差。 需要检查LaTeX格式是否符合要求,行内公式用$...$,独立公式用$$...$$,并正确换行。例如,在堆排序中,可能需要用公式表示堆的结构,或者归并排序的分治步骤。 可能遇到的难点是确保每个步骤描述清晰,比如基数排序的每一趟分配和收集过程,计数排序的计数数组和累加过程。需要用具体的数字示例,让用户更容易理解。 还要注意术语的中文表达是否正确,比如“折半”而不是“二分”,“希尔”排序的音译是否正确。同时,保持结构清晰,分点列出每个排序的原理和步骤,使用标题和分段,帮助用户逐步理解。 最后,确保回答真实可靠,没有遗漏关键步骤或错误,比如在快速排序中基准元素的选择和分区的正确性,归并排序的合并操作是否正确处理剩余元素等。可能需要多次检查每个例子中的数字变化是否正确,避免误导用户。</think>以下是对常见排序算法的原理分析及示例演示(以序列[8, 3, 5, 1, 2]为例): --- ### 一、直接插入排序 **原理**:将未排序元素逐个插入已排序序列的正确位置 **过程演示**: ``` 初始序列:[8|3,5,1,2] # | 左边为已排序区 第1趟: [3,8|5,1,2] # 插入3 第2趟: [3,5,8|1,2] # 插入5 第3趟: [1,3,5,8|2] # 插入1 第4趟: [1,2,3,5,8] # 插入2 ``` --- ### 二、折半插入排序 **原理**:在直接插入排序基础上,用二分查找确定插入位置 **过程演示**: ``` 插入5时:在[3,8]中使用二分法找到插入位置1 插入1时:在[3,5,8]中找到位置0 其他步骤与直接插入相同 ``` --- ### 三、希尔排序 **原理**:按增量分组进行插入排序(示例增量序列:5/2=2) **过程演示**: ``` 增量2分组:[8,5,2]和[3,1] 第1趟组内排序:[2,5,8]和[1,3] → 整体[2,1,5,3,8] 增量1分组:全体元素 第2趟完成排序:[1,2,3,5,8] ``` --- ### 四、冒泡排序 **原理**:相邻元素两两比较,将最大元素"冒泡"到末尾 **过程演示**: ``` 第1趟:[3,5,1,2,8] # 8就位 第2趟:[3,1,2,5,8] # 5就位 第3趟:[1,2,3,5,8] # 3就位 第4趟无交换,排序完成 ``` --- ### 五、快速排序 **原理**:选取基准元素进行分区(示例基准选第一个元素) **过程演示**: ``` 初始基准8 → 分区[3,5,1,2]和[] 左子区基准3 → 分区[1,2]和[5] 继续递归排序,最终得到[1,2,3,5,8] ``` --- ### 六、简单选择排序 **原理**:每次选择最小元素放到已排序序列末尾 **过程演示**: ``` 第1趟选1 → [1|3,5,8,2] 第2趟选2 → [1,2|5,8,3] 第3趟选3 → [1,2,3|8,5] 第4趟选5 → [1,2,3,5,8] ``` --- ### 七、堆排序 **原理**:建立大顶堆,交换堆顶与末尾元素后调整堆 **过程演示**: ``` 建堆:[8,3,5,1,2] → 初始堆结构 第1次交换:8↔2 → 调整堆[5,3,2,1,8] 第2次交换:5↔1 → 调整堆[3,1,2,5,8] ... 最终得到[1,2,3,5,8] ``` --- ### 八、归并排序 **原理**:分治法将序列拆分为子序列,合并时排序 **过程演示**: ``` 拆分至单元素:[8][3][5][1][2] 逐层合并: [3,8] ← 合并[8]和[3] [1,5] ← 合并[5]和[1] [1,2,5] ← 合并[1,5]和[2] 最终合并[3,8]和[1,2,5] → [1,2,3,5,8] ``` --- ### 九、基数排序 **原理**:按位分配收集(示例使用三位数[802, 123, 555, 001, 022]) **过程演示**: ``` 个位分配:0→[802,022], 1→[001], 3→[123], 5→[555] 收集结果:[802,022,001,123,555] 十位分配:0→[802,001], 2→[022,123], 5→[555] 收集结果:[001,802,022,123,555] 百位分配:0→[001], 1→[123], 5→[555], 8→[802] 最终结果:[001,022,123,555,802] ``` --- ### 十、计数排序 **原理**:统计元素出现频率(适用于小范围整数) **过程演示**: ``` 统计数组(假设元素范围0-8): 索引:0 1 2 3 4 5 6 7 8 频次:0 1 1 1 0 1 0 0 1 累加数组得到位置信息:[0,0,1,2,3,3,4,4,4] 反向填充得到有序序列 ``` --- ### 对比总结 | 排序算法 | 时间复杂度 | 稳定性 | 适用场景 | |---------|----------|-------|--------| | 直接插入 | $O(n^2)$ | 稳定 | 小规模/基本有序 | | 希尔排序 | $O(n^{1.3})$ | 不稳定 | 中等规模 | | 快速排序 | $O(n\log n)$ | 不稳定 | 通用排序 | | 堆排序 | $O(n\log n)$ | 不稳定 | 大数据量 | | 归并排序 | $O(n\log n)$ | 稳定 | 外部排序 | | 基数排序 | $O(d(n+k))$ | 稳定 | 多关键字排序 | 需要具体分析某类排序的详细执行过程时,可提供具体示例进行逐步推演。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值