九大经典算法

article/2025/11/10 2:51:00

1. 冒泡排序(Bubble Sort)

两个数比较大小,通过两两交换,像水中的泡泡一样,较大的数下沉,较小的数冒起来。

算法描述

1.比较相邻的元素。如果第一个比第二个大,就交换它们两个;

2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;

3.针对所有的元素重复以上的步骤,除了最后一个;

4.重复步骤1~3,直到排序完成。

动画演示图:

oc代码

- (NSArray*)bubbleSort:(NSArray*)temArr{  

     NSMutableArray *arr = [NSMutableArray arrayWithArray: temArr]; 

     NSInteger count = arr.count;    

    for (int i = 0; i < count; i++) { // 循环次数       

           for (int j = 0; j < count - 1 - i; j++) {  //比较次数          

                  if ([arr[j] intValue] > [arr[j+1] intValue]) {             

                        NSNumber *temp = arr[j];               

                        arr[j] = arr[j + 1];                

                        arr[j + 1] = temp;           

                   }       

            }   

     }   

   return  arr; 

}

swift代码:

func bubbleSort(temArr: [Int] ) -> [Int] {  

       if temArr.count == 0 {        

          return []    

      }    

     var arr = temArray    

     let count = arr.count    

     for  i in 0..<count {  // 循环次数      

            for j in 0..<count - 1 - i { // 比较次数          

                  if (arr[j]  > arr[j + 1] ) {               

                       let temp = arr[j];                

                      arr[j] = arr[j + 1];                

                      arr[j + 1] = temp;            

                 }       

            }   

     }   

 return arr 

}

2.快速排序

1.从数列中挑出一个元素作为基准。

2. 重新排列数列,把所有的比基准小的放在基准前面,反之放在后面(一样大可任意一边)完成后基准处在分区的中间位置。

3. 通过递归调用把小于基准元素和大雨基准元素的子序列进行排序

算法过程图:

oc代码

//数据数组   

NSArray *temArr = @[@30,@40, @60, @10, @20, @50];    

NSMutableArray *arr = [NSMutableArray arrayWithArray:temArr];    

[self quickSort:arr low:0 hight: arr.count - 1];    

NSLog(@"%@",arr);

- (void)quickSort:(NSMutableArray*)temArr low: (NSInteger)low hight: (NSInteger)hight{   

            if (low >= hight) {        

                return;    

            }    

            NSInteger i = low;    

            NSInteger j = hight;   

           id key = temArr[i]; // 参考基数    

           while (i < j) {        

                  while (i < j && [temArr[j] intValue] >= [key intValue]) { // 右边j位大于基数位置不变           

                            j--;        

                 }       

                 if (i == j) { // i、j位置重合结束本次循环,当key是目前最小的数时,会出现i=j的情况,                          

                          break;        

                 }        

                temArr[i] = temArr[j]; //右边j位小于基数位置和i位交换       

               while (i < j && [temArr[i] intValue] <= [key intValue]) {          

                          i++;       

               }       

               if (i == j) { // 当key是目前最大的数时(m[j]的前面),会出现i=j的情况          

                         break;       

               }       

                        temArr[j] = temArr[i];   

       }   

       temArr[i] = key; // i和j重合时本轮循环结束,将key放入i的位置(则左侧数都比key小,右侧数都比key大)    

      // key 的左右分别进行快速排序    

      [self quickSort:temArr low:low hight:i - 1]; // 左递归   

      [self quickSort:temArr low:i + 1 hight:hight]; // 右递归

}

swift代码

var array = [30,40,60,10,20,50] 

quickSort(arr: &array, low: 0, hight: array.count - 1 ) 

print(array)

func quickSort(arr: inout [Int], low: Int, hight: Int ) {   

         if low >= hight {        // 递归结束条件

            return   

         }   

         var i = low;    

         var j = hight;   

         let key = arr[i]  // 基数   

         while i < j {        

                 // 从右边开始比较,比key大的数位置不变

                while  i < j && arr[j] >= key  {           

                          j -= 1       

                }        

               // 只要出现一个比key小的数,将这个数放入左边i的位置        

               arr[i] = arr[j]       

               // 从左边开始比较,比key小的数位置不变        

              while i < j && arr[i] <= key {            

                    i += 1       

              }        

              // 只要出现一个比key大的数,将这个数放入右边j的位置        

              arr[j] = arr[i]   

       }   

      arr[i] = key    // i和j重合时本轮循环结束,将key放入i的位置(则左侧数都比key小,右侧数都比key大)    

      // key 的左右分别进行快速排序    

      quickSort(arr: &arr, low: low, hight: i - 1)    // 左递归    

      quickSort(arr: &arr, low: i + 1, hight: hight)  // 右递归 

}

3.插入排序(Insertion Sort)

1.从第一个元素开始,该元素可以认为已经被排序;

2.取出下一个元素,在已经排序的元素序列中从后向前扫描;

3.如果该元素(已排序)大于新元素,将该元素移到下一位置;

4.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;

5.将新元素插入到该位置后;

6.重复步骤2~5。

动画演示图:

 

 

 

OC代码:

- (NSArray*)insertionSort:(NSArray*)temArr{   

      NSMutableArray *arr = [NSMutableArray arrayWithArray: temArr];    

      NSInteger count = arr.count;   

      for (int i = 0; i < count; i++) { // 循环次数       

          // 从已排序的部分中查找 arr[i] 合适的位置插入       

           for (int j = i; j > 0; j--) {  // 内循环

                  if ([arr[j-1] intValue] > [arr[j] intValue]) {               

                       NSNumber *temp = arr[j];               

                        arr[j] = arr[j - 1];                

                        arr[j - 1] = temp;           

                   } else {       

                       // 因前面是已排序的,故当不满足比较条件即可结束内循环(肯定比前面的值更大)

                        break;           

                  }       

          }   

   }   

   return arr; 

}

swift 代码:

func insertSort(temArr: [Int] ) -> [Int] {  

    if temArr.count == 0 {        

       return []   

     }   

    var arr = temArray   

    let count = arr.count    

    for  i in 0..<count {  // 交换次数        

           // 从已排序的部分中查找 arr[i] 合适的位置插入       

          var j = I         

         while (j > 0) {            

                    if (arr[j-1]  > arr[j] ) {              

                          let temp = arr[j];                

                          arr[j] = arr[j - 1];              

                          arr[j - 1] = temp;          

                   } else {                

                   // 因前面是已排序的,故只要不满足比较条件即可结束内循环,如肯定比前面的值更大                            

                        break;            

                   }         

                  j-=1;       

           }   

     }    

    return arr

}

4.希尔排序(Shell Sort)

   希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序,同时该算法是冲破O(n2)的第一批算法之一。它与插入排序的不同之处在于,它会优先比较距离较远的元素

算法描述

1. 选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;

2. 按增量序列个数k,对序列进行k 趟排序;

3. 每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

动画演示图


OC代码:

- (NSArray*)shellSort:(NSArray*)temArr{    

        NSMutableArray *arr = [NSMutableArray arrayWithArray: temArr];    

       NSInteger count = arr.count;    NSInteger gap = count / 2;   //间隔系数    

       while(gap > 0) {  // if的作用        

              for (NSInteger i = gap; i < count; i++) { // 遍数--分组           

                     NSNumber *temp = arr[i];            

                     NSInteger preIndex = i - gap;            

                     while (preIndex >= 0 && [arr[preIndex] intValue] > [temp intValue]) { // 判断位置交换               

                               arr[preIndex + gap] = arr[preIndex];               

                               preIndex -= gap;           

                      }           

                     arr[preIndex + gap] = temp;       

            }        

          gap /= 2;   

    }    

    return arr; 

}

swift代码:

func shellSort(temArr: [Int] ) -> [Int] {    

          if temArr.count == 0 {      

               return []   

          }   

         var arr = temArray   

          let count = arr.count    

          var gap = count / 2   //间隔系数   

          while gap > 0 {  // if的作用        

             for i in gap..<count { // 遍数--分组           

                     let temp = arr[i]            

                     var preIndex = i - gap           

                     while preIndex >= 0 && arr[preIndex] > temp { // 判断位置交换                

                           arr[preIndex + gap] = arr[preIndex]               

                           preIndex -= gap           

                     }           

                     arr[preIndex + gap] = temp       

               }        

               gap /= 2   

          }   

         return arr 

}

5. 选择排序(Select Sort)

选择排序是直观的排序,从头依次找出最大(或最小值),和排序元素换位。未排序元素继续重复排序操作。直到排序完毕。 双重循环时间复杂度为 O(n^2)

动画演示图:

算法过程图:

 

OC代码:

//数据数组       

NSArray *arr = @[@3,@44, @38, @5, @47, @15, @36, @26, @27, @2, @46, @4, @19, @50, @48];        

// 方法调用

NSArray *sortArray = [self selectSort:arr];    

NSLog(@"%@",sortArray);

// 选择排序代码

- (NSArray *)selectSort:(NSArray*)temArr{   

  NSMutableArray *arr = [NSMutableArray arrayWithArray: temArr];                                           

  NSInteger count = arr.count;   

  for (int i = 0; i < count; i++) {   // 交换次数    

        // 先假设每次循环时,最小数的索引为i        

        int minIndex = i; // 每一个元素都和剩下的未排序的元素比较       

        for (int j = i + 1; j < count; j++) {           

             if ([arr[minIndex] intValue] > [arr[j] intValue]) { //寻找最小数  

                minIndex = j; //将最小数的索引保存          

             }        

        }       

       //经过一轮循环,就可以找出第一个最小值的索引,然后把最小值放到i的位置        

      NSNumber *temp = arr[i];       

      arr[i] = arr[minIndex];        

       arr[minIndex] = temp;   

   }    

 return arr;

}

swift 代码:

// 待排序数组

var temArray = [3,44,38,5,47,15,36,26,27,2,46,4,19,50,48] 

// 调用方法

let sortArray = selectSort(temArr: temArray) 

// 定义选择排序方法

func selectSort2(temArr: [Int] ) -> [Int] {  

    if temArr.count == 0 {     

        return []  

     }   

    var arr = temArray    

    let count = arr.count   

    for  i in 0..<count {        

       // 交换次数        

      // 先假设每次循环时,最小数的索引为i        

     var minIndex = i // 每一个元素都和剩下的未排序的元素比较        

     for j in i+1..<count {           

          if arr[minIndex] > arr[j] { //寻找最小数                

             minIndex = j //将最小数的索引保存          

          }       

      }        

     //经过一轮循环,就可以找出第一个最小值的索引,然后把最小值放到i的位置       

     let temp = arr[i]        

     arr[i] = arr[minIndex]       

      arr[minIndex] = temp    

  }    

return arr

}

6.堆排序

思路分析:

堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆

大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]  

小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2] 

堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了

动图展示:

OC代码:

- (void)heapSort:(NSMutableArray*)arr{     

        //1.构建大顶堆   

        for (NSInteger i = arr.count/2 -1 ; i >= 0; i--) {        

             //从第一个非叶子结点从下至上,从右至左调整结构       

             [self adjustHeap:arr i:i length:arr.count];   

        }     

        //2.调整堆结构+交换堆顶元素与末尾元素    

        for (NSInteger j = arr.count - 1; j > 0; j--) {        

              //将堆顶元素与末尾元素进行交换       

              NSNumber *temp = arr[0];        

              arr[0] = arr[j];        

              arr[j] = temp;        

              //重新对堆进行调整       

              [self adjustHeap:arr i:0 length:j];    

         } 

}

/**  调整大顶堆(仅是调整过程,建立在大顶堆已构建的基础上) */ 

- (void)adjustHeap:(NSMutableArray*)arr i: (NSInteger)i length: (NSInteger)length{       

            NSNumber *temp = arr[i];     

            for (NSInteger k = i*2+1; k < length; k = k*2+1) {        

                      //如果右孩子大于做孩子,则指向右孩子

                     if (k+1 < length && [arr[k] intValue]< [arr[k + 1] intValue]) {           

                              k++;       

                      }        

                      //如果最大的孩子大于当前节点,则将大孩子赋给当前节点,修改当前节点为其大孩子节点,再向下走。

                      if ([arr[k] intValue] >  [temp intValue]) {            

                              arr[i] = arr[k];           

                              i = k;        

                      } else {            

                              break;       

                     }   

            }    

           //将temp放到最终位置

           arr[i] = temp; 

}


http://chatgpt.dhexx.cn/article/2tUiCAkA.shtml

相关文章

最常用的五大算法

一、贪心算法 贪心算法&#xff08;又称贪婪算法&#xff09;是指&#xff0c;在对问题求解时&#xff0c;总是做出在当前看来是最好的选择。也就是说&#xff0c;不从整体最优上加以考虑&#xff0c;他所做出的仅是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整…

几种经典算法

1.分治法 分治法也叫做分而治之法。核心思想是将一个难以直接解决的大问题依照相同的概念分割成两个或者多个相同的小问题&#xff0c;以便各个击破。 如图所示&#xff1a; 2.递归法 递归法和分而治之法像一对孪生兄弟&#xff0c;都是将一个复杂的算法问题进行分解&#x…

五大常用经典算法—分治算法

原文作者&#xff1a;bigsai 原文地址&#xff1a;五大常用算法&#xff1a;一文搞懂分治算法 目录 前言 分治算法介绍 分治算法经典问题 二分搜索 快速排序 归并排序(逆序数) 最大子序列和 最近点对 结语 前言 分治算法&#xff08;divide and conquer&#xff09;是…

十大经典算法

十大经典排序算法&#xff08;动图演示&#xff09; 0、算法概述 0.1 算法分类 十种常见排序算法可以分为两大类&#xff1a; 非线性时间比较类排序&#xff1a;通过比较来决定元素间的相对次序&#xff0c;由于其时间复杂度不能突破O(nlogn)&#xff0c;因此称为非线性时间比…

OpenX系列标准:OpenDRIVE标准简述

1.概述 ​ 作为一个完整的仿真测试场景描述方案&#xff0c;OpenX系列标准包括&#xff1a;OpenDRIVE、OpenSCENARIO和OpenCRG。 标准文件格式文件内容OpenDRIVE.xodr静态部分&#xff08;如道路拓扑结构、交通标志标线等&#xff09;OpenDRIVE.tdo保存ROD项目时生成的文件&a…

OpenDRIVE坐标系解读

几种坐标系简述 opendrive标准主要包括三种坐标系&#xff1a;inertial(x, y, z)、reference line(s, t, h)、local(u, v, z) 下面这张图片笔者认为还是比较清晰的展示了三种坐标系的关系的&#xff1a; 惯性坐标系&#xff08;Inertial&#xff09; 惯性坐标系最简单&am…

《OpenDRIVE1.6规格文档》6

目录 12 标志12.1 针对标志的车道有效性12.2 标志依赖12.3 标志与物体之间的链接12.4 标志放置12.5 标志信息的复用12.6 控制器 13 铁路13.1 铁轨13.2 转辙器13.2.1 主轨道13.2.2 次轨道13.2.3 搭档转辙器 13.3 车站13.3.1 站台13.3.2 段 14 插图目录15 表格目录 12 标志 如图…

《OpenDRIVE1.6规格文档》4

目录 9.5.7 车道高度9.5.8 从道路超高程中排除车道 9.6 道路标识9.6.1 路标类型和线条9.6.2 显性路标类型和线条9.6.3 路标偏移 9.7 特定车道规则 10 交叉口10.1 来路10.2 联接道路10.2.1 交叉口中联接道路的优先级10.2.2 联接道路的方向 10.3 交叉口内的道路表面10.4 虚拟交叉…

opendrive地理坐标

通过使用基于PROJ&#xff08;一种用于两个坐标系之间数据交换的格式&#xff09;的投影字符串来完成对大地基准的描述。该数据应标为CDATA&#xff0c;因为其可能包含会干预元素属性XML语义的字符。 具体参数参考官方文档&#xff1a;Quick start — PROJ 9.2.0 documentatio…

OpenDRIVE地图图形化

OpenDRIVE地图图形化 前言一、 p l a n V i e w planView planView参数三次曲线弧线螺旋线 二、 e l e v a t i o n P r o f i l e elevationProfile elevationProfile三、 l a t e r a l P r o f i l e lateralProfile lateralProfile总结 前言 关于 O p e n D R I V E OpenD…

opendrive中的几何形状

道路的走向可以是多种多样的&#xff0c;可以是空旷地面上的直线、高速公路上细长的弯道、亦或山区狭窄的转弯。为从数学角度对所有这些道路线进行正确建模&#xff0c;OpenDRIVE提供了多种几何形状元素。 图19展示了五种定义道路参考线几何形状的可行方式&#xff1a; 直线螺…

opendrive中的Road

路网在OpenDRIVE中用 <road> 元素来表示。每条道路都沿一条道路参考线延伸。一条道路必须拥有至少一条宽度大于0的车道。 OpenDrive中的道路可以与真实路网中或为应用而设的路网中的道路相提并论。每条道路由一个或多个 <road> 元素描述。一个 <road> 元素可…

opendrive文件结构

1、 文件结构 OpenDRIVE数据存储于XML文件中&#xff0c;文件拓展名为.xodr。OpenDRIVE压缩文件的拓展名为".xodrz"&#xff08;压缩格式gzip&#xff09;。 OpenDRIVE文件的结构符合XML规则&#xff1b;关联的模式文件在XML中得到引用。用于OpenDRIVE格式的模式文…

opendrive中的Lanes

在OpenDRIVE中&#xff0c;所有道路都包含了车道。每条道路必须拥有至少一条宽度大于0的车道&#xff0c;并且每条道路的车道数量不受限制。 需要使用中心车道对OpenDRIVE中的车道进行定义和描述。中心车道没有宽度&#xff0c;并被用作车道编号的参考&#xff0c;自身的车道编…

opendrive坐标系

1 opendrive坐标系概况 OpenDRIVE使用三种类型的坐标系&#xff0c;如下图所示&#xff1a; 惯性x/y/z轴坐标系参考线s/t/h轴坐标系局部u/v/z轴坐标系 若无另外说明&#xff0c;对局部坐标系的查找与定位将相对于参考线坐标系来进行。对参考线坐标系位置与方向的设定则相对于…

OpenDrive里XY和ST

1.坐标系 根据维基百科&#xff0c;坐标系是指&#xff1a;定义一个n维系统&#xff0c;能够使每一个点和一组n个标量组成一一对应的系统。[1] 在坐标系里&#xff0c;有几个关键概念。 第一个关键概念是维度&#xff08;Dimension&#xff09;。维度是指通过一定标准&#xff…

[OpenDrive] OpenDrive学习笔记

文章目录 OpenDRIVEreference linelaneslane offsetlane sectionslane propertiessuperelevation and crossfalllateral profileroad linkagejunctionsneighbors 总体结构Apollo OpenDRIVEApollo OpenDRIVE结构 OpenDRIVE OpenDRIVE是对路网结构的描述性文件&#xff0c;于200…

opendrive简介

1、概要 ASAM OpenDRIVE描述了自动驾驶仿真应用所需的静态道路交通网络&#xff0c;并提供了标准交换格式说明文档。该标准的主要任务是对道路及道路上的物体进行描述。OpenDRIVE说明文档涵盖对如道路、车道、交叉路口等内容进行建模的描述&#xff0c;但其中并不包含动态内容…

如何使用OpenDRIVE

文章目录 OpenDRIVE Notes#1 前言#2 OpenDRIVE结构#2.1 Road#2.1.1 道路属性#2.1.2 道路联接#2.1.3 参考线 #2.2 laneSection#2.3 laneOffset#2.4 junction#2.4.1 路口的联接 #2.5 poly3(三次多项式) #3 解析#3.1 数据结构#3.1.1 ID#3.1.2 Point #4 构建topo#5 邻接点#6 路径规…

《OpenDRIVE1.6规格文档》1

目录 1 前言1.1 说明文档的可交付内容 2 介绍2.1 概要2.2 规范和非规范的声明与可交付内容2.3 惯例2.3.1 命名惯例2.3.2 单位2.3.3 情态动词2.3.4 拼写惯例2.3.5 ID的使用2.3.6 曲率 3 与其它标准的关联(初步)3.1 ASAM OpenDRIVE在ASAM标准系列中的角色3.2 OpenDRIVE与OpenCRG以…