当前位置: 首页 > news >正文

面试常用排序查找算法

文章目录

      • 1 二分查找
      • 2 冒泡排序
      • 3 堆排序
      • 4 插入排序
      • 5 快速排序
      • 6 选择排序
      • 7 希尔排序

1 二分查找

  1. 定义两个变量leftright,分别表示数组的左边界和右边界,初始值分别为0len - 1,其中len是数组的长度。
  2. 计算数组的中间位置mid,公式为(left + right) / 2,并判断数组中该位置的元素num[mid]是否等于目标值target
  3. 如果相等,说明找到了目标值,返回mid作为结果。
  4. 如果不相等,比较num[mid]target的大小,如果num[mid] < target,说明目标值在数组的右半部分,因此将左边界更新为mid + 1;如果num[mid] > target,说明目标值在数组的左半部分,因此将右边界更新为mid - 1
  5. 重复步骤2到4,直到左边界大于右边界,这时说明数组中不存在目标值,返回-1作为结果。

  二分查找算法的优点是查找速度快,时间复杂度为 O ( l o g n ) O(logn) O(logn),其中n是数组的长度。缺点是要求数组必须是有序的,并且对于动态变化的数组不适用。

int BinarySearch(int num[],int target,int len)
{int left = 0, right = len - 1;while(left <= right){int mid = (left + right) / 2;if(num[mid]==target){return mid;}else if(num[mid] < target){left = mid + 1;}else{right = mid - 1;}}return -1;
}

2 冒泡排序

  1. 定义一个变量i,表示数组中未排序的部分的最后一个元素的位置,初始值为length - 1,其中length是数组的长度。
  2. 从数组的第一个元素开始,依次比较相邻的两个元素,如果前一个元素num[j]大于后一个元素num[j+1],则交换它们的位置,这样可以将较大的元素向后移动。
  3. 重复步骤2,直到遍历到数组中未排序部分的最后一个元素,这时可以确定该元素是数组中最大的元素,并将其排在正确的位置。
  4. 将变量i减一,表示数组中未排序部分的长度减少了一个元素,然后回到步骤2,继续进行比较和交换。
  5. 重复步骤2到4,直到变量i小于等于1,这时说明数组中所有的元素都已经排好序,算法结束。

  冒泡排序算法的优点是简单易懂,不需要额外的空间。缺点是效率低,时间复杂度为 O ( n 2 ) O(n^2) O(n2),其中n是数组的长度。

void BubbleSort(int num[],int length)
{for(int i=length-1;i>1;i--){for(int j=0;j<i;j++){if(num[j] > num[j+1]){int tmp = num[j+1];num[j+1] = num[j];num[j] = tmp;}}}
}

3 堆排序

  1. 定义一个函数MaxHeap,它的作用是将一个数组中的一部分元素调整为一个大根堆,即满足父节点的值大于等于子节点的值的二叉树。函数的参数有三个,分别是num表示数组,start表示调整的起始位置,end表示调整的结束位置。
  2. 在函数MaxHeap中,定义两个变量dadson,分别表示当前要调整的父节点和子节点的位置,初始值分别为startstart * 2 + 1(因为数组下标从0开始,所以左子节点是父节点乘以2再加1)。
  3. 判断子节点是否在调整范围内,如果是,则继续执行以下步骤;如果不是,则说明已经调整完毕,返回。
  4. 如果存在右子节点,并且右子节点的值大于左子节点的值,则将子节点更新为右子节点(即选择较大的子节点)。
  5. 比较父节点和子节点的值,如果父节点的值大于等于子节点的值,则说明已经满足大根堆的性质,返回;如果不是,则交换父节点和子节点的值,并将父节点更新为原来的子节点,子节点更新为原来父节点的左子节点(即向下一层继续调整)。
  6. 重复步骤3到5,直到调整完毕或者返回。
  7. 定义一个函数HeapSort,它的作用是对一个数组进行堆排序。函数的参数有两个,分别是num表示数组,len表示数组的长度。
  8. 从数组中间位置开始,依次对每个元素执行函数MaxHeap,这样可以将整个数组调整为一个大根堆(即第一个元素是最大的元素)。
  9. 从数组最后一个元素开始,依次执行以下步骤:
    • 交换第一个元素和当前元素的值,这样可以将最大的元素放在正确的位置。
    • 对除了当前元素之外的其他元素执行函数MaxHeap,这样可以将剩余部分重新调整为一个大根堆(即第一个元素是剩余部分最大的元素)。
  10. 重复步骤9,直到只剩下第一个元素,这时说明数组中所有的元素都已经排好序,算法结束。

  堆排序算法的优点是效率高,时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn),其中n是数组的长度。缺点是需要额外的空间来存储堆结构,并且对于稳定性要求高的场合不适用。

void MaxHeap(int num[],int start,int end)
{int dad = start;int son = dad * 2 + 1;while(son <=end){if((son+1<=end) && (num[son]<num[son+1])){son++;}if(num[son]<num[dad]){return;}else{int tmp = num[dad];num[dad] = num[son];num[son] = tmp;dad = son;son = dad * 2 + 1;}}
}void HeapSort(int num[],int len)
{for(int i=len/2-1;i>=0;i--){MaxHeap(num,i,len-1);}for(int i=len-1;i>0;i--){int tmp = num[0];num[0] = num[i];num[i] = tmp;MaxHeap(num,0,i-1);}
}

4 插入排序

  1. 定义一个变量i,表示当前要插入的元素的位置,初始值为1,表示从数组的第二个元素开始。
  2. 将当前要插入的元素num[i]保存在一个临时变量tmp中,以免被覆盖。
  3. 定义一个变量j,表示已经排好序的部分的最后一个元素的位置,初始值为i - 1
  4. 比较已经排好序的部分的最后一个元素num[j]和要插入的元素tmp的大小,如果前者大于后者,则将前者向后移动一位,即将num[j]赋值给num[j+1],并将j减一;如果不是,则说明找到了要插入的位置,跳出循环。
  5. 将要插入的元素tmp赋值给找到的位置,即将tmp赋值给num[j+1]
  6. 将变量i加一,表示要插入下一个元素,并回到步骤2,继续进行比较和移动。
  7. 重复步骤2到6,直到变量i等于数组的长度,这时说明数组中所有的元素都已经排好序,算法结束。

  插入排序算法的优点是简单易懂,对于部分有序或者数据量较小的数组效率较高。缺点是效率低,时间复杂度为 O ( n 2 ) O(n^2) O(n2),其中n是数组的长度。

void InsertSort(int num[],int length)
{for(int i=1;i<length;i++){int tmp = num[i];int j = i - 1;while((j>=0) && (num[j]>tmp)){num[j+1] = num[j];j--;}num[j+1] = tmp;}
}

5 快速排序

  1. 定义一个函数QuickSort,它的作用是对一个数组的一部分进行快速排序。函数的参数有三个,分别是num表示数组,start表示排序的起始位置,end表示排序的结束位置。
  2. 判断是否需要排序,如果起始位置大于等于结束位置,则说明已经排好序,返回;如果不是,则继续执行以下步骤。
  3. 定义两个变量ij,分别表示当前要划分的部分的左边界和右边界,初始值分别为startend
  4. 选择数组中第一个元素num[i]作为基准值,并将其保存在一个临时变量basenum中,以免被覆盖。
  5. 从右边界开始,向左寻找一个小于基准值的元素,如果找到,则将其赋值给左边界位置;如果没有找到,则将右边界减一,继续寻找。
  6. 从左边界开始,向右寻找一个大于基准值的元素,如果找到,则将其赋值给右边界位置;如果没有找到,则将左边界加一,继续寻找。
  7. 重复步骤5和6,直到左边界和右边界相遇或者交叉,这时说明已经完成了一次划分,并将基准值赋值给相遇或者交叉的位置。
  8. 对基准值左边的部分递归地执行函数QuickSort,对基准值右边的部分递归地执行函数QuickSort
  9. 重复步骤2到8,直到所有的部分都排好序,算法结束。

  快速排序算法的优点是效率高,时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn),其中n是数组的长度。缺点是不稳定,并且对于极端情况(如数组已经有序或者逆序)效率低。

void QuickSort(int num[],int start,int end)
{if(start >= end) return;int i = start;int j = end;int basenum = num[i];while(i<j){//从右往左找小值while((i<j) && (num[j]>=basenum)){j--;}if(i<j){num[i] = num[j];i++;}//从左往右找大值while((i<j) && (num[i]<basenum)){i++;}if(i<j){num[j] = num[i];j--;}num[i] = basenum;}QuickSort(num,start,i-1);QuickSort(num,i+1,end);
}

6 选择排序

  1. 定义一个变量i,表示当前要选择的位置,初始值为0,表示从数组的第一个元素开始。
  2. 定义一个变量min,表示当前最小元素的位置,初始值为i
  3. 从当前位置开始,向后遍历数组中的每个元素,如果发现有比当前最小元素更小的元素,则将其位置赋值给min,这样可以找到当前范围内最小的元素。
  4. 交换当前位置和最小元素的值,即将num[min]赋值给num[i],将num[i]赋值给num[min],这样可以将最小的元素放在正确的位置。
  5. 将变量i加一,表示要选择下一个位置,并回到步骤2,继续进行选择和交换。
  6. 重复步骤2到5,直到变量i等于数组的长度减一,这时说明数组中所有的元素都已经排好序,算法结束。

  选择排序算法的优点是简单易懂,不需要额外的空间。缺点是效率低,时间复杂度为 O ( n 2 ) O(n^2) O(n2),其中n是数组的长度。

void SelectSort(int num[],int length)
{for(int i=0;i<length-1;i++){int min = i;for(int j=i;j<length;j++){if(num[j]<num[min]){min = j;}}int tmp = num[min];num[min] = num[i];num[i] = tmp;}
}

7 希尔排序

  1. 定义一个变量gap,表示当前要排序的元素的间隔,初始值为数组的长度length
  2. 计算新的间隔,公式为gap = gap / 3 + 1,这样可以逐渐减小间隔,直到为1。
  3. 对每个间隔进行以下步骤:
    • 定义一个变量i,表示当前要排序的间隔的起始位置,初始值为0
    • 从当前位置开始,向后遍历数组中的每个间隔内的元素,如果发现有比前一个间隔内的元素更小的元素,则将其保存在一个临时变量tmp中,并执行以下步骤:
      • 定义一个变量k,表示已经排好序的部分的最后一个间隔内的元素的位置,初始值为当前位置减去间隔,即k = j - gap
      • 比较已经排好序的部分的最后一个间隔内的元素num[k]和要插入的元素tmp的大小,如果前者大于后者,则将前者向后移动一个间隔,即将num[k]赋值给num[k+gap],并将k减去间隔,继续比较;如果不是,则说明找到了要插入的位置,跳出循环。
      • 将要插入的元素tmp赋值给找到的位置,即将tmp赋值给num[k+gap]
    • 将变量i加一,表示要排序下一个间隔,并回到步骤3.2,继续进行遍历和插入。
  4. 重复步骤2和3,直到变量gap等于1,这时说明数组中所有的元素都已经排好序,算法结束。

  希尔排序算法的优点是效率高于简单插入排序,时间复杂度为 O ( n 1.3 ) O(n^{1.3}) O(n1.3),其中n是数组的长度。缺点是不稳定,并且对于不同的间隔选择效率有影响。

void ShellSort(int num[],int length)
{int gap = length;do{gap = gap / 3 + 1;for(int i=0;i<gap;i++){for(int j=gap+i;j<length;j+=gap){if(num[j] < num[j-gap]){int tmp = num[j];int k;for(k=j-gap;(k>=0) && (num[k]>tmp);k-=gap){num[k+gap] = num[k];}num[k+gap] = tmp;}}}} while(gap>1);
}

相关文章:

面试常用排序查找算法

文章目录 1 二分查找2 冒泡排序3 堆排序4 插入排序5 快速排序6 选择排序7 希尔排序 1 二分查找 定义两个变量left和right&#xff0c;分别表示数组的左边界和右边界&#xff0c;初始值分别为0和len - 1&#xff0c;其中len是数组的长度。计算数组的中间位置mid&#xff0c;公式…...

CUDA C编程权威指南:1.1-CUDA基础知识点梳理

主要整理了N多年前&#xff08;2013年&#xff09;学习CUDA的时候开始总结的知识点&#xff0c;好长时间不写CUDA代码了&#xff0c;现在LLM推理需要重新学习CUDA编程&#xff0c;看来出来混迟早要还的。 1.CUDA 解析&#xff1a;2007年&#xff0c;NVIDIA推出CUDA&#xff08…...

讲讲项目里的仪表盘编辑器(四)分页卡和布局容器组件

讲讲两个经典布局组件的实现 ① 布局容器组件 配置面板是给用户配置布局容器背景颜色等属性。这里我们不需要关注 定义文件 规定了组件类的类型、标签、图标、默认布局属性、主文件等等。 // index.js import Container from ./container.vue; class ContainerControl extends…...

Qt模块、Qt开发应用程序类型、Qt未来主要市场、Qt6功能普及

Qt模块、Qt开发应用程序类型、Qt未来主要市场、Qt6功能普及 文章目录 1.Qt核心模块2.Qt的功能拓展3.Qt未来主要市场4.Qt6功能普及5.弃用的功能&#xff1a; Qt是一个跨平台的应用程序开发框架&#xff0c;提供了丰富的模块和工具来开发各种类型的应用程序。以下是Qt目前已有的…...

nodejs+vue高校校图书馆elementui

管理员输入书籍所在的书架位置&#xff0c;借阅提醒系统&#xff1a;可以查看个人借阅信息和图书到期提醒、挂失、检索、虚拟借书证不仅为群众提供了服务&#xff0c;而且也推广了自己&#xff0c;让更多的群众了解自己。 管理员页面&#xff1a; 第三章 系统分析 10 3.1需求分…...

CUDA C编程权威指南:1.2-CUDA基础知识点梳理

主要整理了N多年前&#xff08;2013年&#xff09;学习CUDA的时候开始总结的知识点&#xff0c;好长时间不写CUDA代码了&#xff0c;现在LLM推理需要重新学习CUDA编程&#xff0c;看来出来混迟早要还的。 1.闭扫描和开扫描   对于一个二元运算符 ⊕ \oplus ⊕和一个 n n n元…...

C语言—位运算符

目录 &&#xff08;位与&#xff0c;AND&#xff09;&#xff1a; |&#xff08;位或&#xff0c;OR&#xff09;&#xff1a; 位取反(~)&#xff1a; 左移(<<)&#xff1a; 右移(>>)&#xff1a; &&#xff08;位与&#xff0c;AND&#xff09;&…...

怎么才能实现一个链接自动识别安卓.apk苹果.ipa手机和win电脑wac电脑

您想要实现的功能是通过检测用户代理&#xff08;User Agent&#xff09;来识别访问设备类型并根据设备类型展示相应的页面。您可以根据以下步骤进行实现&#xff1a; 选择后端语言和框架&#xff0c;例如&#xff1a;Node.js、Express。 创建一个新的Express项目。 编写一个…...

zookeeper选举机制

全新集群选举 zookeeper 全新集群选举机制网上资料很多说法很模糊&#xff0c;仔细思考了一下&#xff0c;应该是这样 得到票数最多的机器>机器总数半数 具体启动过程中的哪个节点成为 leader 与 zoo.cfg 中配置的节点数有关&#xff0c;下面以3个举例 选举过程如下 server…...

vcpkg切换 Visual Studio 版本

vcpkg切换 Visual Studio 版本 在使用vcpkg作为项目的包管理工具时&#xff0c;可能会遇到需要切换Visual Studio版本的情况。下面是一种简单的方法来实现这个目标&#xff0c;通过修改triplet文件来指定使用的Visual Studio版本。 步骤1: 创建或修改Triplet文件 首先&#…...

运算符重载

#include <iostream> using namespace std; class Num { private:int num1; //实部int num2; //虚部 public:Num(){}; //无参构造Num(int n1,int n2):num1(n1),num2(n2){}; //有参构造~Num(){}; //析构函数const Num operator(const Num &other)const //加号重载{Nu…...

Llama2-Chinese项目:7-外延能力LangChain集成

本文介绍了Llama2模型集成LangChain框架的具体实现&#xff0c;这样可更方便地基于Llama2开发文档检索、问答机器人和智能体应用等。 1.调用Llama2类   针对LangChain[1]框架封装的Llama2 LLM类见examples/llama2_for_langchain.py&#xff0c;调用代码如下所示&#xff1a;…...

ES6中数组的扩展

1. 扩展运算符 用三个点(...)表示&#xff0c;它如同rest参数的逆运算&#xff0c;将数组转为用逗号分隔的参数序列。扩展就是将一个集合分成一个个的。 console.log(...[1, 2, 3]); // 1, 2, 3可以用于函数调用 扩展运算符后还可以放置表达式 ...(x > 0 ? [a] : [])如…...

计算机考研 | 2016年 | 计算机组成原理真题

文章目录 【计算机组成原理2016年真题44题-9分】【第一步&#xff1a;信息提取】【第二步&#xff1a;具体解答】 【计算机组成原理2016年真题45题-14分】【第一步&#xff1a;信息提取】【第二步&#xff1a;具体解答】 【计算机组成原理2016年真题44题-9分】 假定CPU主频为5…...

Web版Photoshop来了,用到了哪些前端技术?

经过 Adobe 工程师多年来的努力&#xff0c;并与 Chrome 等浏览器供应商密切合作&#xff0c;通过 WebAssembly Emscripten、Web Components Lit、Service Workers Workbox 和新的 Web API 的支持&#xff0c;终于在近期推出了 Web 版 Photoshop&#xff08;photoshop.adobe…...

FL Studio21.1.0水果中文官方网站

FL Studio 21.1.0官方中文版重磅发布纯正简体中文支持&#xff0c;更快捷的音频剪辑及素材管理器&#xff0c;多样主题随心换&#xff01;Mac版新增对苹果M2/1家族芯片原生支持。DAW界萌神&#xff01;极富二次元造型的水果娘FL chan通过FL插件Fruity Dance登场&#xff0c;为其…...

[BJDCTF2020]Mark loves cat

先用dirsearch扫一下&#xff0c;访问一下没有什么 需要设置线程 dirsearch -u http://8996e81f-a75c-4180-b0ad-226d97ba61b2.node4.buuoj.cn:81/ --timeout2 -t 1 -x 400,403,404,500,503,429使用githack python2 GitHack.py http://8996e81f-a75c-4180-b0ad-226d97ba61b2.…...

@SpringBootApplication注解的理解——如何排除自动装配 分布式情况下如何自动加载 nacos是怎么被发现的

前言 spring作为主流的 Java Web 开发的开源框架&#xff0c;是Java 世界最为成功的框架&#xff0c;持续不断深入认识spring框架是Java程序员不变的追求。 本篇博客介绍SpringBootApplicant注解的自动加载相关内容 其他相关的Spring博客文章列表如下&#xff1a; Spring基…...

HTTP的前世今生

史前时期 20 世纪 60 年代&#xff0c;美国国防部高等研究计划署&#xff08;ARPA&#xff09;建立了 ARPA 网&#xff0c;它有四个分布在各地的节点&#xff0c;被认为是如今互联网的“始祖”。 然后在 70 年代&#xff0c;基于对 ARPA 网的实践和思考&#xff0c;研究人员发…...

软件测试教程 自动化测试selenium篇(二)

掌握Selenium常用的API的使用 目录 一、webdriver API 1.1元素的定位 1.2 id定位 1.3name 定位 1.4tag name 定位和class name 定位 1.5CSS 定位 1.6XPath 定位 1.7link text定位 1.8Partial link text 定位 二、操作测试对象 2.1鼠标点击与键盘输入 2.2submit 提交…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录

ASP.NET Core 是一个跨平台的开源框架&#xff0c;用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录&#xff0c;以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

免费PDF转图片工具

免费PDF转图片工具 一款简单易用的PDF转图片工具&#xff0c;可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件&#xff0c;也不需要在线上传文件&#xff0c;保护您的隐私。 工具截图 主要特点 &#x1f680; 快速转换&#xff1a;本地转换&#xff0c;无需等待上…...

HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散

前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说&#xff0c;在叠衣服的过程中&#xff0c;我会带着团队对比各种模型、方法、策略&#xff0c;毕竟针对各个场景始终寻找更优的解决方案&#xff0c;是我个人和我司「七月在线」的职责之一 且个人认为&#xff0c…...