Python实现基于二叉树存储结构的堆排序算法示例


Posted in Python onDecember 08, 2017

本文实例讲述了Python实现基于二叉树存储结构的堆排序算法。分享给大家供大家参考,具体如下:

既然用Python实现了二叉树,当然要写点东西练练手。

网络上堆排序的教程很多,但是却几乎都是以数组存储的数,直接以下标访问元素,当然这样是完全没有问题的,实现简单,访问速度快,也容易理解。

但是以练手的角度来看,我还是写了一个二叉树存储结构的堆排序

其中最难的问题就是交换二叉树中两个节点。

因为一个节点最多与三个节点相连,那么两个节点互换,就需要考虑到5个节点之间的关系,也需要判断是左右孩子,这将是十分繁琐的,也很容易出错。

class Tree:
  def __init__(self, val = '#', left = None, right = None):
    self.val = val
    self.left = left
    self.right = right
    self.ponit = None
    self.father = None
    self.counter = 0
  #前序构建二叉树
  def FrontBuildTree(self):
    temp = input('Please Input: ')
    node = Tree(temp)
    if(temp != '#'):
      node.left = self.FrontBuildTree()
      node.right = self.FrontBuildTree()
    return node#因为没有引用也没有指针,所以就把新的节点给返回回去
    #前序遍历二叉树
  def VisitNode(self):
    print(self.val)
    if(self.left != None):
      self.left.VisitNode()
    if(self.right != None):
      self.right.VisitNode()
  #中序遍历二叉树
  def MVisitTree(self):
    if(self.left != None):
      self.left.MVisitTree()
    print(self.val)
    if(self.right != None):
      self.right.MVisitTree()
  #获取二叉树的第dec个节点
  def GetPoint(self, dec):
    road = str(bin(dec))[3:]
    p = self
    for r in road:
      if (r == '0'):
        p = p.left
      else:
        p = p.right
    #print('p.val = ', p.val)
    return p
  #构建第一个堆
  def BuildHeadTree(self, List):
    for val in List:
      #print('val = ', val, 'self.counter = ', self.counter)
      self.ponit = self.GetPoint(int((self.counter + 1) / 2))
      #print('self.ponit.val = ', self.ponit.val)
      if (self.counter == 0):
        self.val = val
        self.father = self
      else:
        temp = self.counter + 1
        node = Tree(val)
        node.father = self.ponit
        if(temp % 2 == 0):#新增节点为左孩子
          self.ponit.left = node
        else:
          self.ponit.right = node
        while(temp != 0):
          if (node.val < node.father.val):#如果新增节点比其父亲节点值要大
            p = node.father#先将其三个链子保存起来
            LeftTemp = node.left
            RightTemp = node.right
            if (p.father != p):#判断其不是头结点
              if (int(temp / 2) % 2 == 0):#新增节点的父亲为左孩子
                p.father.left = node
              else:
                p.father.right = node
              node.father = p.father
            else:
              node.father = node#是头结点则将其father连向自身
              node.counter = self.counter
              self = node
            if(temp % 2 == 0):#新增节点为左孩子
              node.left = p
              node.right = p.right
              if (p.right != None):
                p.right.father = node
            else:
              node.left = p.left
              node.right = p
              if (p.left != None):
                p.left.father = node
            p.left = LeftTemp
            p.right = RightTemp
            p.father = node
            temp = int(temp / 2)
            #print('node.val = ', node.val, 'node.father.val = ', node.father.val)
            #print('Tree = ')
            #self.VisitNode()
          else:
            break;
      self.counter += 1
    return self
  #将头结点取出后重新调整堆
  def Adjust(self):
    #print('FrontSelfTree = ')
    #self.VisitNode()
    #print('MSelfTree = ')
    #self.MVisitTree()
    print('Get ', self.val)
    p = self.GetPoint(self.counter)
    #print('p.val = ', p.val)
    #print('p.father.val = ', p.father.val)
    root = p
    if (self.counter % 2 == 0):
      p.father.left = None
    else:
      p.father.right = None
    #print('self.left = ', self.left.val)
    #print('self.right = ', self.right.val)
    p.father = p#将二叉树最后一个叶子节点移到头结点
    p.left = self.left
    p.right = self.right
    while(1):#优化是万恶之源
      LeftTemp = p.left
      RightTemp = p.right
      FatherTemp = p.father
      if (p.left != None and p.right !=None):#判断此时正在处理的结点的左后孩子情况
        if (p.left.val < p.right.val):
          next = p.left
        else:
          next = p.right
        if (p.val < next.val):
          break;
      elif (p.left == None and p.right != None and p.val > p.right.val):
        next = p.right
      elif (p.right == None and p.left != None and p.val > p.left.val):
        next = p.left
      else:
        break;
      p.left = next.left
      p.right = next.right
      p.father = next
      if (next.left != None):#之后就是一系列的交换节点的链的处理
        next.left.father = p
      if (next.right != None):
        next.right.father = p
      if (FatherTemp == p):
        next.father = next
        root = next
      else:
        next.father == FatherTemp
        if (FatherTemp.left == p):
          FatherTemp.left = next
        else:
          FatherTemp.right = next
      if (next == LeftTemp):
        next.right = RightTemp
        next.left = p
        if (RightTemp != None):
          RightTemp.father = next
      else:
        next.left = LeftTemp
        next.right = p
        if (LeftTemp != None):
          LeftTemp.father = next
      #print('Tree = ')
      #root.VisitNode()
    root.counter = self.counter - 1
    return root
if __name__ == '__main__':
  print("三水点靠木测试结果")
  root = Tree()
  number = [-1, -1, 0, 0, 0, 12, 22, 3, 5, 4, 3, 1, 6, 9]
  root = root.BuildHeadTree(number)
  while(root.counter != 0):
    root = root.Adjust()

运行结果:

Python实现基于二叉树存储结构的堆排序算法示例

Python 相关文章推荐
举例讲解Python编程中对线程锁的使用
Jul 12 Python
Python全局变量用法实例分析
Jul 19 Python
Python进阶篇之字典操作总结
Nov 16 Python
git进行版本控制心得详谈
Dec 10 Python
Python基于pyCUDA实现GPU加速并行计算功能入门教程
Jun 19 Python
python3利用venv配置虚拟环境及过程中的小问题小结
Aug 01 Python
详解Python可视化神器Yellowbrick使用
Nov 11 Python
Pytorch 计算误判率,计算准确率,计算召回率的例子
Jan 18 Python
Python flask路由间传递变量实例详解
Jun 03 Python
通过实例解析python创建进程常用方法
Jun 19 Python
Python+Selenium实现自动化的环境搭建的步骤(图文)
Sep 01 Python
PyTorch dropout设置训练和测试模式的实现
May 27 Python
Python排序搜索基本算法之堆排序实例详解
Dec 08 #Python
基于Django contrib Comments 评论模块(详解)
Dec 08 #Python
Python数据分析中Groupby用法之通过字典或Series进行分组的实例
Dec 08 #Python
python在ubuntu中的几种安装方法(小结)
Dec 08 #Python
Python编程之gui程序实现简单文件浏览器代码
Dec 08 #Python
Python中的pygal安装和绘制直方图代码分享
Dec 08 #Python
python的unittest测试类代码实例
Dec 07 #Python
You might like
PHP中$_SERVER的详细参数与说明介绍
2013/10/26 PHP
php实现的mysqldb读写分离操作类示例
2017/02/07 PHP
PHP时间类完整代码实例
2021/02/26 PHP
用javascript连接access数据库的方法
2006/11/17 Javascript
ppk谈JavaScript style属性
2008/10/10 Javascript
Firefox下提示illegal character并出现乱码的原因
2010/03/25 Javascript
读jQuery之十 事件模块概述
2011/06/27 Javascript
ie9 提示'console' 未定义问题的解决方法
2014/03/20 Javascript
实现网页页面跳转的几种方法(meta标签、js实现、php实现)
2014/05/20 Javascript
jQuery源码分析之jQuery中的循环技巧详解
2014/09/06 Javascript
JavaScript操作URL的相关内容集锦
2015/10/29 Javascript
Bootstrap导航栏各元素操作方法(表单、按钮、文本)
2015/12/28 Javascript
javascript每日必学之多态
2016/02/23 Javascript
Javascript中 toFixed四舍六入方法
2017/08/21 Javascript
JS使用setInterval实现的简单计时器功能示例
2018/04/19 Javascript
原生js封装的ajax方法示例
2018/08/02 Javascript
在vue项目中引用Iview的方法
2018/09/14 Javascript
atom-design(Vue.js移动端组件库)手势组件使用教程
2019/05/16 Javascript
Electron + vue 打包桌面操作流程详解
2019/06/24 Javascript
layui实现数据表格table分页功能(ajax异步)
2019/07/27 Javascript
js数据类型转换与流程控制操作实例分析
2019/12/18 Javascript
详细分析vue表单数据的绑定
2020/07/20 Javascript
Python实例分享:快速查找出被挂马的文件
2014/06/08 Python
Python读取txt内容写入xls格式excel中的方法
2018/10/11 Python
python Selenium实现付费音乐批量下载的实现方法
2019/01/24 Python
使用 Python 合并多个格式一致的 Excel 文件(推荐)
2019/12/09 Python
如何解决flask修改静态资源后缓存文件不能及时更改问题
2020/08/02 Python
英国户外装备商店:Ultimate Outdoors
2019/05/07 全球购物
自荐信的禁忌和要点
2013/10/15 职场文书
人事部经理岗位职责
2014/03/07 职场文书
总经理助理的职责
2014/03/14 职场文书
如何写贫困证明申请书
2014/10/29 职场文书
2014年初一班主任工作总结
2014/11/08 职场文书
孝老爱亲事迹材料
2014/12/24 职场文书
教师思想工作总结2015
2015/05/13 职场文书
MySQL表字段时间设置默认值
2021/05/13 MySQL