用递归法求汉诺塔问题Python,Python递归算法经典实例

  用递归法求汉诺塔问题Python,Python递归算法经典实例

  每次对越来越少的元素重复上述步骤,直到没有要比较的数字对。

  2.动画演示

  3.Python代码实现

  def bubbleSort(数组):

  对于范围内的I(1,len(arr)):

  对于范围(0,len(arr)-i)中的j:

  if arr[j] arr[j 1]:

  数组[j],数组[j 1]=数组[j 1],数组[j]

  返回arr

  选择排序法

  选择是一种简单直观的排序算法。不管什么数据进去,都是O(n2)的时间复杂度。所以在使用的时候,数据量越小越好。唯一的好处可能就是不占用额外的内存空间。

  1.算法步骤

  首先,在未排序的序列中找到最小(最大)的元素,并将其存储在已排序序列的开头。

  然后继续从剩余的未排序元素中寻找最小(最大)的元素,然后放在排序后的序列的末尾。

  重复第二步,直到所有元素都排序完毕。

  2.动画演示

  3.Python代码实现

  定义选择排序(arr):

  对于范围内的I(len(arr)-1):

  #记录最小数量的索引

  minIndex=i

  对于范围内的j(I ^ 1,len(arr)):

  if arr[j] arr[minIndex]:

  minIndex=j

  当# i不是最小数时,用最小数交换I。

  如果我!=minIndex:

  arr[i],arr[minIndex]=arr[minIndex],arr[i]

  返回arr

  插入排序

  虽然插入排序的代码实现没有冒泡排序和选择性排序那么简单粗暴,但是它的原理应该是最容易理解的,因为玩过扑克的人应该都能秒懂。插入是最简单、最直观的排序算法。它的工作原理是在排序后的序列中从后向前扫描未排序的数据,找到对应的位置并插入。

  和冒泡排序一样,插入排序也有一个优化算法,叫做对半插入。

  1.算法步骤

  第一个待排序序列的第一个元素被视为有序序列,第二个元素到最后一个元素被视为未排序序列。

  从头到尾扫描无序序列,将每个扫描的元素插入有序序列的适当位置。(如果要插入的元素等于有序序列中的一个元素,则将要插入的元素插入到等于的元素之后。)

  2.动画演示

  3.Python代码实现

  定义插入排序(arr):

  对于范围内的I(len(arr)):

  preIndex=i-1

  current=arr[i]

  preIndex=0且arr[preIndex] current:

  arr[preIndex 1]=arr[preIndex]

  preIndex-=1

  arr[preIndex 1]=当前

  返回arr

  谢尔分类

  Hill排序,也称为降序增量排序算法,是插入排序的一个更高效的改进版本。然而,希尔排序算法是不稳定的。

  希尔排序基于插入排序的以下两个属性:

  在对几乎排序的数据进行操作时,插入排序是高效的,即可以达到线性排序的效率;

  但是插入排序一般效率不高,因为插入排序一次只能移动一位数据;

  Hill排序的基本思路是:首先,将待排序的整个记录序列分成若干子序列进行直接插入排序。当整个序列中的记录都是‘基本有序’时,直接插入所有记录并依次排序。

  1.算法步骤

  选择增量序列t1,t2,tk,其中ti tj,tk=1;

  根据增量序列的个数k,对序列进行k次排序;

  每次排序时,根据对应的增量ti,将待排序的列分成若干个长度为m的子序列,每个子表直接插入排序。当增量因子只有1时,整个序列被当作一个表,表的长度就是整个序列的长度。

  2.Python代码实现

  定义外壳排序(arr):

  导入数学

  差距=1

  while(gap len(arr)/3):

  差距=差距*3 1

  而间隙0:

  对于范围内的I(gap,len(arr)):

  临时=数组[i]

  j=i-gap

  当j=0且arr[j] temp:

  arr[j缺口]

  间隙

  arr[j gap]=温度

  gap=math.floor(gap/3)

  返回arr

  合并分类

  归并排序是一种基于归并操作的有效排序算法。这个算法是分而治之的典型应用。

  作为分治思想的典型算法应用,归并排序通过两种方法实现:

  自顶向下递归(所有递归方法都可以通过迭代重写,所以有第二种方法);

  自底向上迭代;

  在《数据结构与算法 JavaScript 描述》中,作者给出了一个自底向上的迭代方法。但是对于递归方法,作者认为:

  然而,在JavaScript中这是不可能的,因为递归太深,语言无法处理。

  但是这种方法在JavaScript中并不可行,因为这种算法的递归深度对它来说太深了。

  说实话,这句话我不太懂。是不是说明JavaScript编译器内存太小,太深的递归容易导致内存溢出?希望有大神可以教教我。

  与选择性排序一样,合并排序的性能不受输入数据的影响,但它比选择性排序好得多,因为它总是O(nlogn)的时间复杂度。代价是额外的存储空间。

  1.算法步骤

  申请一个大小为两个排序序列之和的空间,用来存放合并后的序列;

  设置两个指针,其初始位置分别为两个排序序列的初始位置;

  比较两个指针指向的元素,选择一个相对较小的元素放入归并空间,将指针移动到下一个位置;

  重复步骤3,直到指针到达序列的末尾;

  将另一个序列的所有剩余元素直接复制到合并序列的末尾。

  2.动画演示

  3.Python代码实现

  定义合并排序(arr):

  导入数学

  if(len(arr)2):

  返回arr

  middle=math.floor(len(arr)/2)

  left,right=arr[0:middle],arr[middle:]

  返回merge(mergeSort(左),mergeSort(右))

  定义合并(左、右):

  结果=[]

  而左和右:

  如果left[0]=right[0]:

  result . append(left . pop(0));

  否则:

  result . append(right . pop(0));

  离开时:

  result . append(left . pop(0));

  右侧:

  result . append(right . pop(0));

  回送结果

  快速排序

  快速排序是智能豆豆研发的一种排序算法。平均来说,对N个项目进行排序需要 (nlogn)次比较。在最坏的情况下,需要进行 (N2)比较,但这种情况并不常见。事实上,快速排序通常比其他 (NLOGN)算法快得多,因为它的内循环可以在大多数架构中高效实现。

  快速排序使用分治策略将一个列表分成两个子列表。

  快速排序是分治思想在排序算法中的典型应用。本质上,快速排序应该看作是一种基于冒泡排序的递归分治法。

  快速排序这个名字简单粗暴,因为只要一听到这个名字,你就会知道它存在的意义,那就是快速高效!是处理大数据最快的排序算法之一。虽然最坏情况的时间复杂度达到O(n2),但人是优秀的,在大多数情况下,比平均时间复杂度为O(n logn)的排序算法表现更好,但不知道为什么。还好我的强迫症又犯了。查了更多的资料,终于在《算法艺术与信息学竞赛》上找到了满意的答案:

  快速排序最差的情况是O(n2),比如顺序数列的快速排序。但其共享的期望时间为O(nlogn),O(nlogn)标记中隐含的常数因子很小,远小于稳定复杂度等于O(nlogn)的归并排序。所以对于大部分弱序列的随机序列,快速排序总是比归并排序好。

  1.算法步骤

  从序列中挑出一个元素,称之为‘pivot’;

  对数列重新排序,所有小于参考值的元素放在参考值的前面,所有大于参考值的元素放在参考值的后面(相同的数字可以在两边)。在这个分区退出后,基准位于系列的中间。这称为分区操作;

  递归排序小于参考值的元素子序列和大于参考值的元素子序列;

  在递归的最底层,序列的大小是零或一,也就是一直排序下去。虽然它一直在递归,但这种算法总是会退出,因为在每次迭代中,它至少会将一个元素放到最后一个位置。

  2.动画演示

  3.Python代码实现

  def快速排序(arr,left=None,right=None):

  如果不是isinstance,left=0(left,(int,float))否则向左

  right=len(arr)-1 if not is instance(right,(int,float)) else right

  如果向左向右:

  partitionIndex=partition(arr,left,right)

  快速排序(数组,左,分区索引-1)

  快速排序(arr,partitionIndex 1,右)

  返回arr

  定义分区(左右排列):

  枢轴=向左

  索引=透视1

  i=指数

  而我=右:

  if arr[i] arr[pivot]:

  交换(arr,I,index)

  指数=1

  i=1

  交换(数组,透视,索引-1)

  回报指数-1

  def swap(arr,I,j):

  arr[i],arr[j]=arr[j],arr[i]

  堆排序

  堆排序是指利用堆的数据结构设计的一种排序算法。Heap是一种类似于完全二叉树的结构,同时满足heap的性质:即子节点的键值或索引总是小于(或大于)其父节点。堆排序可以说是利用堆的概念进行的一种选择性排序。有两种方法:

  Top heap:每个节点的值大于等于其子节点的值,用于堆排序算法中的升序;

  Top heap:每个节点的值小于等于其子节点的值,用于堆排序算法中的降序;

  堆排序的平均时间复杂度为 (nlogn)。

  1.算法步骤

  创建一个堆h[0…n-1];

  交换反应器头部(最大)和反应器尾部;

  将堆的大小减少1,调用shift_down(0)以便将新数组顶部的数据调整到相应的位置;

  重复步骤2,直到堆栈的大小为1。

  2.动画演示

  3.Python代码实现

  def buildMaxHeap(arr):

  导入数学

  对于范围内的I(math . floor(len(arr)/2),-1,-1):

  heapify(arr,I)

  def heapify(arr,I):

  左=2*i 1

  右=2*i 2

  最大=i

  if left arrLen和arr[left]arr[large]:

  最大=左侧

  如果右arrLen和arr[右]arr[最大]:

  最大=右侧

  如果最大!=我:

  交换(arr,I,最大)

  heapify(arr,最大)

  def swap(arr,I,j):

  arr[i],arr[j]=arr[j],arr[i]

  定义堆排序(arr):

  全球arrLen

  arrLen=len(arr)

  buildMaxHeap(arr)

  对于范围内的I(len(arr)-1,0,-1):

  swap(arr,0,I)

  arrLen -=1

  heapify(arr,0)

  返回arr

  计数排序

  计数排序的核心是将输入的数据值转换成键,存储在额外的数组空间中。作为一种线性时间复杂度的排序,计数排序要求输入数据必须是一定范围内的整数。

  1.动画演示

  2.Python代码实现

  def countingSort(arr,maxValue):

  bucketLen=maxValue 1

  bucket=[0]*bucketLen

  sortedIndex=0

  arrLen=len(arr)

  对于范围内的I(arr len):

  如果不是bucket[arr[i]]:

  bucket[arr[i]]=0

  bucket[arr[i]]=1

  对于范围内的j(bucket len):

  while桶[j]0:

  arr[sortedIndex]=j

  sortedIndex=1

  桶[j]-=1

  返回arr

  桶分类

  桶排序是计数排序的升级版本。它利用了函数的映射关系,高效的关键在于这个映射函数的确定。为了提高桶排序的效率,我们需要做两件事:

  当额外空间足够时,尝试增加桶的数量。

  的映射函数可以将输入的N个数据均匀分布到K个桶中。

  同时,为了对桶中的元素进行排序,选择一个性能比较排序算法是非常重要的。

  1.最快是什么时候?

  当输入数据可以均匀分布到每个桶时。

  2.最慢的时间是什么时候?

  当输入数据被分配到相同的桶时。

  基数排序

  基数排序是一种非比较整数排序算法。它的原理是把整数按照位数切割成不同的数字,然后按照每个数字进行比较。由于整数也可以用特定格式表示字符串(如姓名或日期)和浮点数,所以基数排序不仅可以用于整数。

  1.基数排序vs计数排序vs桶排序

  有两种方法对基数进行排序:

  所有三种排序算法都利用了桶的概念,但是桶的用法有明显的不同:

  基数:根据键值的每一位分配桶;

  计数排序:每个桶只存储一个键值;

  桶排序:每个桶存储一定范围的值;

  2.LSD基数排序动态图的演示

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: