数据结构【排序篇】

数据结构【排序篇】


文章目录

  • 数据结构【排序篇】
  • 前言
    • 为什么突然想学算法了?
    • 为什么选择码蹄集作为刷题软件?
  • 目录
    • 一、插入排序
    • 二、交换排序
    • 三、 选择排序
    • 四、归并排序和基数排序
  • 结语


前言

在这里插入图片描述

为什么突然想学算法了?

> 用较为“官方”的语言讲,是因为算法对计算机科学的所有分支都非常重要。 在绝大多数的计算机科学分支领域中,要想完成任何实质性的工作,理解算法的基础知识并掌握与算法密切相关的数据结构知识是必不可少的。
> 但从实际而言,是因为当下竞争压力逐渐增大,无论走哪一条路,都不免需要一些相对丰富的算法知识,是故,便产生了一个寒假巩固速成算法的计划,可能对于像我这种算法竞赛小白而言,几乎很难,但我仍然还是想尝试一下,毕竟,梦想还是要有的,万一实现了呢?~( ̄▽ ̄~)~

在这里插入图片描述


为什么选择码蹄集作为刷题软件?

码蹄集,是在全国高等学校计算机教学与产业实践资源建设专家委员会(TIPCC) 指导下建设的,其依托全国各大名校计算机系和清华大学出版社等单位的强大资源,旨在为计算机学习爱好者提供全面和权威的计算机习题。
.
在这里插入图片描述


目录

一、插入排序

#include<iostream>

using namespace std;

//直接插入排序
void InsertSort(int A[],int n){
    int i,j,temp;
    for(i=1;i<n;i++)                            //将各元素插入已排好序的序列中
        if(A[i]<A[i-1]){                        //若A[i]关键字小于前驱
            temp=A[i];                          //用temp暂存A[i]
            for(j=i-1;j>=0 && A[j]>temp;--j)    //检查所有前面已排好序的元素
                A[j+1]=A[j];                    //所有大于temp的元素都向后挪位
            A[j+1]=temp;                        //复制到插入位置
        }
}

//直接插入排序(带哨兵)
void InsertSortS(int A[],int n){
    int i,j;
    for(i=2;i<=n;i++)                           //依次将A[2]~A[n]插入到前面已排序序列
        if(A[i]<A[i-1]){                        //若A[i]关键码小于其前驱,将A[i]插入有序表
            A[0]=A[i];                          //复制为哨兵,A[0]不存放元素
            for(j=i-1;j>=0 && A[0]<A[j];--j)    //从后往前查找待插入位置
                A[j+1]=A[j];                    //向后挪位
            A[j+1]=A[0];                        //复制到插入位置
        }
}

//二者本质上都是做了一个临时变量,哨兵A[0]在其中充当temp的作用

//折半插入排序
void MidInsertSort(int A[],int n){
    int i,j,high,low,mid,temp;
    for(i=1;i<n;i++){                           //依次将A[1]~A[n-1]插入前面的已排序序列
        temp=A[i];                              //将A[i]暂存到temp;
        low=0;high=i-1;                         //设置折半查找的范围
        while(low<=high){                       //折半查找(默认递增有序)
            mid=(low+high)/2;                   //取中间点
            if(A[mid]>temp) high=mid-1;         //查找左半子表
            else low=mid+1;                     //查找右半子表
        }
        for(j=i-1;j>=high+1;--j)
            A[j+1]=A[j];                        //统一后移元素,空出插入位置
        A[high+1]=temp;                         //插入操作
    }
}

//希尔排序
void ShellSort(int A[],int n){
    int d,i,j,temp;
    //A[0]只是暂存单元,不是哨兵,当j<=0时,插入位置已到(这里用temp代替)
    for(d=n/2;d>=1;d=d/2)           //增量变化(无统一规定)
        for(i=d+1;i<n;++i)
            if(A[i]<A[i-d]){        //需将A[i]插入有序增量子表
                temp=A[i];          //暂存在A[0]
                for(j=i-d;j>0&&temp<A[j];j-=d)
                    A[j+d]=A[j];     //记录后移,查找插入的位置
                A[j+d]=temp;         //插入
            }
}

int main(){
    int B[10]={10,7,76,5,98,43,2,18,9,10};

    //带哨兵的直接插入排序(从输出结果和理解上看,还是建议用不带哨兵的)
//    InsertSortS(B,10);
//    for(int i=1;i<10;i++) cout<<B[i]<<" ";
//    cout<<endl;

    //不带哨兵的直接插入排序
//    InsertSort(B,10);
//    for(int i=0;i<10;i++) cout<<B[i]<<" ";

    //折半查找
//    MidInsertSort(B,10);
//    for(int i=0;i<10;i++) cout<<B[i]<<" ";



    return 0;
}

二、交换排序


#include<iostream>
using namespace std;

//简单选择排序
void SelectSort(int A[],int n){
    for(int i=0;i<n-1;i++){             //一共进行n-1趟
        int min=i;                      //记录最小元素位置
        for(int j=i+1;j<n;j++)          //在A[i...n-1]中选择最小的元素
            if(A[j]<A[min]) min=j;      //更新最小元素位置
        if(min!=i) swap(A[i],A[min]);   //封装的swap()函数共移动元素3次
    }
}
//交换
void swap(int &a,int &b){
    int temp=a;
    a=b;
    b=temp;
}

//冒泡排序
void BubbleSort(int A[],int n){
    for(int i=0;i<n-1;i++){
        for(int j=n-1;j>i;j--)      //一趟冒泡过程
            if(A[j-1]>A[j]){        //若为逆序
                swap(A[j-1],A[j]);  //交换
            }
    }
}

//用第一个元素将排序序列划分成左右两个部分
int Partition(int A[],int low,int high){
    int pivot=A[low];           //用第一个元素作为枢轴
    while(low<high){            //用low,high搜索枢轴的最终位置
        while (low<high&&A[high]>=pivot) --high;
        A[low]=A[high];         //比枢轴小的元素移动到左端(切勿将顺序进行颠倒)
        while(low<high&&A[low]<=pivot) ++low;
        A[high]=A[low];         //比枢轴大的元素移动到右端
    }
    A[low]=pivot;               //枢轴元素存放到最终位置
    return low;                 //返回存放枢轴的最终位置
}

//快速排序
void QuickSort(int A[],int low,int high){
    if(low<high){               //递归跳出的条件
        int pivotpos= Partition(A,low,high);    //划分
        QuickSort(A,low,pivotpos-1);    //划分左子表
        QuickSort(A,pivotpos+1,high);    //划分右子表
    }
}


int main(){
    int A[10]={49,38,65,97,76,13,27,49,12,32};

    //冒泡排序
//    BubbleSort(A,10);
//    for(int i=0;i<10;i++) cout<<A[i]<<" ";

    //快速排序
    QuickSort(A,0,9);
    for(int i=0;i<10;i++) cout<<A[i]<<" ";
    return 0;
}

三、 选择排序

#include<iostream>
using namespace std;

//简单选择排序
void SelectSort(int A[],int n){
    for(int i=0;i<n-1;i++){             //一共进行n-1趟
        int min=i;                      //记录最小元素位置
        for(int j=i+1;j<n;j++)          //在A[i...n-1]中选择最小的元素
            if(A[j]<A[min]) min=j;      //更新最小元素位置
        if(min!=i) swap(A[i],A[min]);   //封装的swap()函数共移动元素3次
    }
}

//堆排序
//将以k为根的子树调整为大根堆
void HeadAdjust(int A[],int k,int len){
    A[0]=A[k];                      //A[0]暂存子树的根结点
    for(int i=2*k;i<=len;i*=2){     //沿key较大的子结点向下筛选
        if(i<len&&A[i]<A[i+1])
            i++;                    //取Key较大的子结点的下标
        if(A[0]>=A[i]) break;       //筛选结束
        else{
            A[k]=A[i];              //将A[i]调整到双亲结点上
            k=i;                    //修改k值,以便继续向下筛选
        }
    }
    A[k]=A[0];                      //被筛选结点的值放入最终位置
}

//建立大根堆
void BuildMaxHeap(int A[],int len){
    for(int i=len/2;i>0;i--)        //从后往前调整所有非终端结点
        HeadAdjust(A,i,len);
}


//堆排序的完整逻辑
void HeapSort(int A[],int len){
    BuildMaxHeap(A,len);            //初始建堆
    for(int i=len;i>1;i--){         //n-1趟的交换和建堆过程
        swap(A[i],A[1]);            //堆顶元素和堆底元素交换
        HeadAdjust(A,1,i-1); //把剩余的待排序元素整理成堆
    }
}

int main(){
    int A[10]={49,38,65,97,76,13,27,49,12,32};

//    SelectSort(A,10);
//    for(int i=0;i<10;i++) cout<<A[i]<<" ";

    //堆排序
    HeapSort(A,10);
    for(int i=0;i<10;i++) cout<<A[i]<<" ";
    return 0;
}

四、归并排序和基数排序

#include<iostream>
#include <cstring>
#include <valarray>

using namespace std;

int n=10;
int *B = (int *)malloc(n*sizeof(int));      //辅助数组B
//A[low...mid]和A[mid+1...high]各自有序,将两个部分合并
void Merge(int A[],int low,int mid,int high){
    int i,j,k;
    for(k=low;k<=high;k++)
        B[k]=A[k];              //将A中所有元素复制到B中
    for(i=low,j=mid+1,k=i;i<=mid&&j<=high;k++){
        if(B[i]<=B[j])
            A[k]=B[i++];        //将较小值复制到A中
        else
            A[k]=B[j++];
    }
    while(i<=mid)  A[k++]=B[i++];   //若第一个表未检测完,复制
    while(j<=high) A[k++]=B[j++];   //若第二个表未检测完,复制
}

void MergeSort(int A[],int low,int high){
    if(low<high){
        int mid=(low+high)/2;       //从中间划分
        MergeSort(A,low,mid);       //对左半部分归并排序
        MergeSort(A,mid+1,high);//对右半部分归并排序
        Merge(A,low,mid,high);      //归并
    }
}

//基数排序(往年没考过,王道书上也没有对应代码)
void RadixSort(int a[],int n){
    int cnt[15][100005];                          //进行基数排序比较的二维数组
    int max_a=0;
    for(int i=0; i<n; i++){
        max_a = max(max_a, a[i]);                 //寻找最大关键字
    }
    int p=1;                                      //用于进行位数切割
    while(max_a){
        memset(cnt, 0, sizeof cnt);          //用于对数组进行初始化
        for(int i=0; i<n; i++)
            cnt[(a[i]/p) % 10][i] = a[i];         //对数组中的元素进行基数排序
        int l = 0;
        for (int i = 0; i < 10; i ++ ) {          //一列一列放
            for (int j = 0; j < n; j ++ ) {
                if (cnt[i][j]) a[l++] = cnt[i][j];//将结果放回a数组中
            }
        }
        p *= 10;
        max_a /= 10;
    }
}


int main(){
    int A[10]={11,43,10,7,89,10,23,78,9,10};

//    //归并排序
//    MergeSort(A,0,9);
//    for(int i=0;i<10;i++) cout<<A[i]<<" ";

    //基数排序(没考过,大概率不考代码)
    RadixSort(A,10);
    for(int i=0;i<10;i++) cout<<A[i]<<" ";
    return 0;
}


结语

感谢大家一直以来的不断支持与鼓励,码题集题库中的进阶塔350题正在逐步更新,之后会逐步跟进星耀,王者的题,尽请期待!!!
同时,也希望这些题能帮助到大家,一起进步,祝愿每一个算法道路上的“苦行僧”们,都能够历经磨难,终成正果,既然选择了这条路,走到了这里,中途放弃,岂不是太过可惜?

另附中国计算机学会的杰出会员、常务理事轩哥博士的B站视频讲解链接https://space.bilibili.com/518554541/?spm_id_from=333.999.0.0,供大家更好的进行学习与刷题~( ̄▽ ̄~)~

愿你的结局,配得上你一路的颠沛流离。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/292638.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringIOC之support模块DefaultMessageSourceResolvable

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

【ITK库学习】使用itk库进行图像配准:变换Transform(三)

目录 1、itkAffineTransform 仿射变换2、itkBSplineDeformableTransform B样条可变形变换 1、itkAffineTransform 仿射变换 该类实现向量空间的仿射变换&#xff08;例如空间坐标&#xff09; 此类允许定义和操作n维仿射空间&#xff08;及其关联的向量空间&#xff09;对其自…

QT C++调用python传递RGB图像和三维数组,并接受python返回值(图像)

目的&#xff1a; 用QT调用python代码&#xff0c;将QT读取的图像(Qimage)作为参数传入python中&#xff0c;将QT的三维数组作为参数传递给python&#xff0c;python接收QT传入的图像进行计算&#xff0c;将结果返回给QT并显示。 一 .pro 头文件的配置&#xff0c;和lib库的…

在 Mac 上轻松安装和配置 JMeter

Apache JMeter 是一个开源的负载测试工具&#xff0c;可以用于测试静态和动态资源&#xff0c;确定服务器的性能和稳定性。在本文中&#xff0c;我们将讨论如何下载和安装 JMeter。 安装 Java&#xff08;已安装 Java 的此步骤可跳过&#xff09; 要安装 Java&#xff0c;请按…

数字孪生与边缘计算的结合

数字孪生与边缘计算的结合可以在物理实体附近进行实时数据处理和决策&#xff0c;从而提高响应速度、降低延迟&#xff0c;并有效地利用边缘资源。以下是数字孪生在边缘计算中的一些应用&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开…

JavaWeb——后端之SpringBoot基础知识

2. SpringBoot 官网&#xff1a;https://spring.io/ Spring全家桶&#xff1a;Spring已经形成了一种开发生态圈&#xff0c;其提供的若干子项目分别用于完成特定的功能 Spring Boot简化了Spring Framework&#xff0c;不用底层实现那么配置繁琐&#xff0c;可以快速构建应用…

【Java EE初阶八】多线程案例(计时器模型)

1. java标准库的计时器 1.1 关于计时器 计时器类似闹钟&#xff0c;有定时的功能&#xff0c;其主要是到时间就会执行某一操作&#xff0c;即可以指定时间&#xff0c;去执行某一逻辑&#xff08;某一代码&#xff09;。 1.2 计时器的简单介绍 在java标准库中&#xff0c;提供…

ChatGPT怎么帮我上班的

1.解放生产力 1&#xff09;标准格式&#xff0c;完美输出。GPT对于公文等具有一定标准格式的文件&#xff0c;可以进行完美仿写&#xff0c;随随便便以假乱真那都是小菜一碟&#xff0c;这对于经常要开展规范成文的人来说&#xff0c;简直就是个福音&#xff0c;只要前期调教…

使用“反向代理服务器”的优点是什么?

反向代理服务器是一种网络架构模式&#xff0c;通常位于客户端和实际服务器之间&#xff0c;用于处理客户端请求并转发到实际服务器。以下是使用反向代理服务器的优点&#xff1a; 1.安全性&#xff1a;反向代理服务器可以提供额外的安全层。通过在反向代理服务器上配置防火墙和…

Jmeter 性能压测 —— 常见问题

1、怎么确定系统最大负载&#xff1f; 通过负载测试&#xff0c;不断增加用户数&#xff0c;随着用户数的增加&#xff0c;各项性能指标也会相应产生变化&#xff0c;当出现了性能拐点。 比如&#xff0c;当用户数达到某个数量级时&#xff0c;响应时间突然增长&#xff0c;那…

电脑重装后恢复音频输出(安装声卡驱动)

写在前面&#xff1a;本博客仅作记录学习之用&#xff0c;部分图片来自网络&#xff0c;如需引用请注明出处&#xff0c;同时如有侵犯您的权益&#xff0c;请联系删除&#xff01; 文章目录 前言基本设置检查声卡驱动自带Realtek高清晰音频管理器不带Realtek高清晰音频管理器 总…

ROS学习笔记(8)进一步深入了解ROS第二步

0.前提 在上一讲中我提到过该系列是基于宾夕法尼亚大学工程学院的ROS公开课&#xff0c;系列文章将来源于公开课中的课后习题。该系列可以很好的帮助大家更加深入的了解ROS的一些概念。&#xff08;有效面对HR的提问。&#xff09; 1. (C)What is a nodehandle object? Can we…

vscode无识别已有的maven java项目(visual studio code not recognizing java project)

文章目录 事情经过尝试疑惑问题解决结论 事情经过 未安装任何Java Extension Pack使用 Maven 的 archetype:generate 命令来创建一个新的项目使用vscode打开了该目录然后安装Java Extension Pack等java插件配置了vscode settings.json中的 java.configuration.runtimes和 java…

网站迁移和SEO:损害排名的常见错误

正在规划站点迁移&#xff1f; 迁移是更困难的 - 通常是可怕的 - SEO任务之一。 为了让它发挥作用&#xff0c;你需要避免常见的陷阱&#xff0c;这些陷阱可能会影响你的知名度&#xff0c;并导致流量和收入的损失。 8 月 11 日&#xff0c;我主持了一场赞助的搜索引擎杂志网…

TypeScript 从入门到进阶之基础篇(二) ts进阶类型篇

TypeScript 从入门到进阶系列 TypeScript 从入门到进阶之基础篇(一) ts基础类型篇 文章目录 TypeScript 从入门到进阶系列前言一、object 类型1、基础运用2、可选属性3、任意属性4、只读属性 readonly5、对象中的函数 二、数组类型1、数组的运用2、使用接口定义数组3、argumen…

关于标准那些事——第六篇 四象之“玄武”(格式的编排)

两仪生四象——东方青龙&#xff08;木&#xff09;、西方白虎&#xff08;金&#xff09;、南方朱雀&#xff08;火&#xff09;、北方玄武&#xff08;水&#xff09; 分别对应标准编写之四象——层次的编写、要素的编写、要素的表述、格式的编排。 今天来分享一下 格式的编…

Python 标准库中的 csv 包

0. Abstract 官方文档很罗嗦&#xff0c;长篇大论例子少。本文将举例说明 csv 包的用法&#xff0c;然后补充一些必要的说明。 1.0 CSV 文件 CSV(Comma-Separated Values,逗号分隔值)文件是一种常见的以纯文本形式存储数据的文件格式。它使用逗号作为字段之间的分隔符&#…

【Linux】——基本指令(二)

&#x1f497;个人主页&#x1f497; ⭐个人专栏——数据结构学习⭐ &#x1f4ab;点击关注&#x1f929;一起学习C语言&#x1f4af;&#x1f4ab; 目录 导读&#xff1a;1. vim 指令2. head指令3. tail指令4. tree指令5. 输出重定向6. echo指令7. wc指令8. | 字符9. date指令…

CMake入门教程【核心篇】属性管理set_property和get_property

&#x1f608;「CSDN主页」&#xff1a;传送门 &#x1f608;「Bilibil首页」&#xff1a;传送门 &#x1f608;「本文的内容」&#xff1a;CMake入门教程 &#x1f608;「动动你的小手」&#xff1a;点赞&#x1f44d;收藏⭐️评论&#x1f4dd; 文章目录 1.概述2.设置属性 - …

JS中 focus 和 blur 焦点事件

发现的一个小知识点 focus 获取焦点事件 代码如下&#xff1a; <body><input type"text" placeholder"input输入框"><script>let input document.querySelector(input)input.addEventListener(focus, function (e) {e.target.style.…