当前位置:首页 > 科技  > 软件

教你利用二叉树的思想,轻松解决合并排序和快速

来源: 责编: 时间:2023-10-30 17:23:50 461观看
导读排序在我们的的工程应用中无处不见,也有着非常重要的作用,比如你随意点开一个搜索引擎,搜索的结构就是经过排序而来。各种电商网站的秒杀活动,用户点击秒杀后,服务器会根据用户的请求时间进行排序。在我们的用的文档表格中

排序在我们的的工程应用中无处不见,也有着非常重要的作用,比如你随意点开一个搜索引擎,搜索的结构就是经过排序而来。各种电商网站的秒杀活动,用户点击秒杀后,服务器会根据用户的请求时间进行排序。在我们的用的文档表格中,也存在各种排序。EZ628资讯网——每日最新资讯28at.com

所以排序真的是无处不见,因此,面试中出现关于排序的算法题也就不足为奇了。这篇文章通过面试中最经常出现的两种排序算法进行深度展开。EZ628资讯网——每日最新资讯28at.com

  • 合并排序
  • 快速排序

本文你将收获相应的思想和代码模板。EZ628资讯网——每日最新资讯28at.com

1.合并排序

合并排序本质上与二叉树的后序遍历非常类似的。EZ628资讯网——每日最新资讯28at.com

// 递归function postOrder(root, array = []) {  if (root === null) return null;  postOrder(root.left, array);  postOrder(root.right, array);  array.push(root.val)}

后序遍历有个三个重要的特点:EZ628资讯网——每日最新资讯28at.com

  • 拿到子树的信息;
  • 利用子树的信息;
  • 整合树的信息;

这三个特点对应到合并排序就是:EZ628资讯网——每日最新资讯28at.com

  • 拿到子数组的信息;
  • 利用子数组的信息;
  • 排序出数组的信息。

利用伪代码来表示就是:EZ628资讯网——每日最新资讯28at.com

function 后序遍历/合并排序:    子结构划分    sub = 子结构(子树/子数组)    full = 整合(sub)

这个伪代码总结为三个关键点:EZ628资讯网——每日最新资讯28at.com

  • 划分子结构
  • 获取子结构的信息
  • 利用子结构的信息整合成结果

划分子结构

二叉树,子树的划分已经在数据结构里面约定好了:EZ628资讯网——每日最新资讯28at.com

root.leftroot.right

数组,子结构的划分,如果想到达最优的效率,那么将数组切为平均的两半效率应该是最高的。EZ628资讯网——每日最新资讯28at.com

const mid = begin + ((end - begin)>>1)数组a = [begin, mid) => 表示左子数组数组a = [mid, end) => 表示右子数组

获取子结构的信息

二叉树,获取子树的信息的利用就是遍历左右子节点的信息。EZ628资讯网——每日最新资讯28at.com

postOrder(root.left)postOrder(root.right)

合并排序,获取子数组的信息就是对左子数组和右子数组进行排序。对子数组的排序,只需要递归就可以了。EZ628资讯网——每日最新资讯28at.com

merge(a, begin, mid)merge(a, mid, end)

利用子结构的信息整合成结果

二叉树,结果的合成就是将节点值添加到结果中。EZ628资讯网——每日最新资讯28at.com

array.push(root.val)

合并排序,结果的合成,我们需要将两个有序的子数组,合并成一个大的有序的数组。EZ628资讯网——每日最新资讯28at.com

let i = begin;let j = mid;let to = begin;// 将两个数组合并,判断条件是,只有左右子数组中还有元素while(i < mid || j < end) {  // 读取左数组的元素:  //   - 左数组还存在元素并且左数组的开头元素小于右数组的开头元素  //    - 右数组没有元素  if ((i < mid && a[i] < a[j]) || j >=end) {    // t 为临时数组    t[to++] = a[i++];  } else {  // 读取右数组的元素    t[to++] = a[j++];    }}

最后

最后,处理边界:EZ628资讯网——每日最新资讯28at.com

二叉树的边界就是节点不能为空。EZ628资讯网——每日最新资讯28at.com

if (root === null) return null;

合并排序的边界就是:EZ628资讯网——每日最新资讯28at.com

  • 当 b >= e,说明这个区间是一个空区间,没有必要再排序;
  • 当 b + 1 === e,说明只有一个元素,也没有必要排序。
if (b > e || b + 1 >= e) {  return }

小结

二叉树,代码如下。EZ628资讯网——每日最新资讯28at.com

function postOrder(root, array = []) {  // 边界处理  if (root === null) return null;  // 第一步:划分子结构,二叉树在结构上已经划分了子结构 root.left、root.right 可以直接通过树的子节点拿  // 第二步:获取子结构信息(递归的方式)  postOrder(root.left, array);  postOrder(root.right, array);  // 第三步:整合子结构信息  array.push(root.val)}

合并排序,如何切分左右子数组?如何进行合并,合并时注意循环的条件,以及稳定排序的写法?都是在写算法时需要注意的。整体代码如下:EZ628资讯网——每日最新资讯28at.com

function merge(a, t, b, e) { // 边界处理  if (b > e || b + 1 >= e) {    return   } /*********************核心代码****************************/  // 第一步:划分子结构  const mid = b + ((e-b)>>1);  // 第二步:获取子结构信息(递归的方式)  merge(a, t, b, mid); // 左边子结构  merge(a, t, mid, e); // 右边子结构  // 第三步:整合子结构信息  let i = b;  let j = mid;  let to = b;  // 注意:下面是一个很重要的模板❤❤❤❤❤❤❤❤❤❤❤❤ // 将两个数组合并,判断条件是,只有左右子数组中还有元素  while(i < mid || j < e) {    // 读取左数组的元素:    //   - 左数组还存在元素并且左数组的开头元素小于右数组的开头元素    //    - 右数组没有元素   if ((i < mid && a[i] < a[j]) || j >=e) {      t[to++] = a[i++];    } else {    // 读取右数组的元素      t[to++] = a[j++];      }  } /*********************核心代码****************************/  // 将合并的结果拷贝到源数组中  for (let i = b; i < e; i++) {    a[i] = t[i];  }}function mergeSort(nums) {  if (nums === null || nums.length === 0) {    return;  }  merge(nums, [], 0, nums.length)  return nums;}

2.快速排序

快速排序和合并排序一样,可以利用二叉树的思想来解决,合并排序本质上与二叉树的后序遍历非常类似的,而快速排序本质上与二叉树的前序遍历非常类似的。EZ628资讯网——每日最新资讯28at.com

前序遍历:EZ628资讯网——每日最新资讯28at.com

// 递归function preOrder(root, array = []) {  if (root === null) return null;  array.push(root.val);  postOrder(root.left, array);  postOrder(root.right, array);}

后序遍历有个三个重要的特点:EZ628资讯网——每日最新资讯28at.com

  • 整合树的信息;
  • 拿到子树的信息;
  • 利用子树的信息;

这三个特点对应到合并排序就是:EZ628资讯网——每日最新资讯28at.com

  • 排序出数组的信息。
  • 拿到子数组的信息;
  • 利用子数组的信息;

利用伪代码来表示就是:EZ628资讯网——每日最新资讯28at.com

function 前序遍历/快速排序():    子结构划分    获取根节点信息;    将根节点的信息传递左右子树/左右子数组;

这个伪代码总结为三个关键点:EZ628资讯网——每日最新资讯28at.com

  • 划分子结构
  • 根节点的信息处理
  • 将根节点的信息,传递给左右子树/左右子数组。

划分子结构

二叉树,子树的划分已经在数据结构里面约定好了:EZ628资讯网——每日最新资讯28at.com

root.leftroot.right

数组,子结构的划分,选择一个数 X,并且利用这个数,将数组分成三部分:EZ628资讯网——每日最新资讯28at.com

  • 小于 X 的部分;
  • 等于 X 的部分;
  • 大于 X 的部分;
利用 x 将数组分为三份左子数组 = [小于 x 的部分] = [b, l)根节点 = [等于 x 的部分] = [l, i)右子数组 = [大于 x 的部分] = [i, e)

根节点的信息处理

二叉树,根节点就是当前节点,节点的处理也即是收集节点信息。EZ628资讯网——每日最新资讯28at.com

// 根节点信息处理array.push(root.val);

排序算法的"根节点"也就是选择的元素,并且排序算法会通过划分的子结构和选中的元素来进行排序处理也就是上面说的特殊处理;对于排序算法来说,"根节点"和划分子结构息息相关。EZ628资讯网——每日最新资讯28at.com

if (a[i] < x) {    // 小于 x 的部分} else if (a[i] === x) {    // 等于 x 的部分} else {    // 大于 x 的部分}

将根节点的信息,传递给左右子树/左右子数组

二叉树,通过递归的方式处理左右子树。EZ628资讯网——每日最新资讯28at.com

// 二叉树的前序遍历拿左右子树的信息preOrder(root.left);preOrder(root.right);

而排序算法需要分别对左子数组和右子数组进行排序,那么类似的对子数组的排序应该也只需要递归就可以了。EZ628资讯网——每日最新资讯28at.com

// 快速排序去拿左右子数组的信息qsort(a, b, l);qsort(a, i, e);

最后

最后,不管是二叉树还是快速排序都要考虑一下边界:EZ628资讯网——每日最新资讯28at.com

二叉树的边界就是节点不能为空。EZ628资讯网——每日最新资讯28at.com

if (root === null) return null;

快速排序的边界就是:EZ628资讯网——每日最新资讯28at.com

  • 当 b >= e,说明这个区间是一个空区间,没有必要再排序;
  • 当 b + 1 === e,说明只有一个元素,也没有必要排序。
if (b > e || b + 1 >= e) {  return;}

小结

二叉树,代码如下。EZ628资讯网——每日最新资讯28at.com

function preOrder(root, array = []) {  // 边界处理  if (root === null) return null;  // 第一步:划分子结构,二叉树在结构上已经划分了子结构 root.left、root.right 可以直接通过树的子节点拿  // 第二步:根节点的信息处理  array.push(root.val)  // 第三步:将根节点的信息,传递给左右子树/左右子数组(递归的方式)  postOrder(root.left, array);  postOrder(root.right, array);}

对于快速排序来说,如何划分子结构?如何到达最优的效率?都是在写算法时需要注意的。整体代码如下:EZ628资讯网——每日最新资讯28at.com

// 交换数组中两个元素的值 function swap(A, i, j) {  const t = A[i];  A[i] = A[j];  A[j] = t;}function qsort(a, begin, end) {    // 边界情况   if (b > e || b + 1 >= e) {     return    } /*********************核心代码****************************/ // 第一步:划分子结构    const mid = b + ((end - begin) >> 1); // 第二步:获取根节点信息 x const x = a[mid]; // 根据 x 将数组一分为三 【三路切分】 let l = begin; let i = begin; let r = end - 1;    while(i < r) {        if (a[i] < x) {            // 小于 x 的部分            swap(a, l++, i++);        } else if (a[i] === x) {            // 等于 x 的部分            i++;        } else {            // 大于 x 的部分            swap(a, r--, i);        }    } // 第三步:将根节点的信息传递左右子子树 qsort(a, b, l); qsort(a, i, e); /*********************核心代码****************************/}// 主函数,将数组nums排序 function quickSort(nums) {  if (nums == null)    return;  qsort(nums, 0, nums.length);}

总结

通过合并排序和快速排序,可以得出结论,数组其实是另外一种形式的二叉树,只不过有时候需要我们动态地把左/右子树给切分出来,不同的切分方式,可以解决不同的问题。大家也可以自己思考和尝试,看看还能不能发现更多排序的特点和巧妙用法,并且将它们总结下来。欢迎大家一起在评论区交流。EZ628资讯网——每日最新资讯28at.com

参考

  • https://leetcode.cn/problems/median-of-two-sorted-arrays/solutions/258842/xun-zhao-liang-ge-you-xu-shu-zu-de-zhong-wei-s-114/
  • https://kaiwu.lagou.com/course/courseInfo.htm?courseId=685#/detail/pc?id=6697
  • https://juejin.cn/post/7286307632193273915
  • https://juejin.cn/post/7287914116296458275
  • https://juejin.cn/post/7287473826060304445

本文链接:http://www.28at.com/showinfo-26-15858-0.html教你利用二叉树的思想,轻松解决合并排序和快速

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 可以提取图像文本的五大 Python 库

下一篇: 了解Springboot起步依赖及其实现原理

标签:
  • 热门焦点
  • K60 Pro官方停产 第三方瞬间涨价

    虽然没有官方宣布,但Redmi的一些高管也已经透露了,Redmi K60 Pro已经停产且不会补货,这一切都是为了即将到来的K60 Ultra铺路,属于厂家的正常操作。但有意思的是该机在停产之后
  • Mate60手机壳曝光 致敬自己的经典设计

    8月3日消息,今天下午博主数码闲聊站带来了华为Mate60的第三方手机壳图,可以让我们在真机发布之前看看这款华为全新旗舰的大致轮廓。从曝光的图片看,Mate 60背后摄像头面积依然
  • 分享六款相见恨晚的PPT模版网站, 祝你做出精美的PPT!

    1、OfficePLUSOfficePLUS网站旨在为全球Office用户提供丰富的高品质原创PPT模板、实用文档、数据图表及个性化定制服务。优点:OfficePLUS是微软官方网站,囊括PPT模板、Word模
  • 学习JavaScript的10个理由...

    作者 | Simplilearn编译 | 王瑞平当你决心学习一门语言的时候,很难选择到底应该学习哪一门,常用的语言有Python、Java、JavaScript、C/CPP、PHP、Swift、C#、Ruby、Objective-
  • 一文搞定Java NIO,以及各种奇葩流

    大家好,我是哪吒。很多朋友问我,如何才能学好IO流,对各种流的概念,云里雾里的,不求甚解。用到的时候,现百度,功能虽然实现了,但是为什么用这个?不知道。更别说效率问题了~下次再遇到,
  • 大厂卷向扁平化

    来源:新熵作者丨南枝 编辑丨月见大厂职级不香了。俗话说,兵无常势,水无常形,互联网企业调整职级体系并不稀奇。7月13日,淘宝天猫集团启动了近年来最大的人力制度改革,目前已形成一
  • 华为Mate 60系列用上可变灵动岛:正式版体验将会更出色

    这段时间以来,关于华为新旗舰的爆料日渐密集。据此前多方爆料,今年华为将开始恢复一年双旗舰战略,除上半年推出的P60系列外,往年下半年的Mate系列也将
  • 苹果、三星、惠普等暂停向印度出口笔记本和平板电脑

    集微网消息,据彭博社报道,在8月3日印度突然禁止在没有许可证的情况下向印度进口电脑/平板及显示器等产品后,苹果、三星电子和惠普等大公司暂停向印度
  • iQOO 11S新品发布会

    iQOO将在7月4日19:00举行新品发布会,推出杭州亚运会电竞赛事官方用机iQOO 11S。
Top