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 相关文章推荐
使用httplib模块来制作Python下HTTP客户端的方法
Jun 19 Python
基于进程内通讯的python聊天室实现方法
Jun 28 Python
python 禁止函数修改列表的实现方法
Aug 03 Python
Python进阶学习之特殊方法实例详析
Dec 01 Python
python编写分类决策树的代码
Dec 21 Python
关于Django显示时间你应该知道的一些问题
Dec 25 Python
python实现随机漫步算法
Aug 27 Python
python使用Matplotlib画条形图
Mar 25 Python
详解django实现自定义manage命令的扩展
Aug 13 Python
python 连续不等式语法糖实例
Apr 15 Python
python如何写个俄罗斯方块
Nov 06 Python
Python爬虫之Selenium实现窗口截图
Dec 04 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
用Socket发送电子邮件(利用需要验证的SMTP服务器)
2006/10/09 PHP
用文本作数据处理
2006/10/09 PHP
域名查询代码公布
2006/10/09 PHP
用php实现像JSP,ASP里Application那样的全局变量
2007/01/12 PHP
Dwz与thinkphp整合下的数据导出到Excel实例
2014/12/04 PHP
PHP实现将MySQL重复ID二维数组重组为三维数组的方法
2016/08/01 PHP
Javascript实例教程(19) 使用HoTMetal(3)
2006/12/23 Javascript
调试代码导致IE出错的避免方法
2014/04/04 Javascript
Javascript基础教程之数据类型 (布尔型 Boolean)
2015/01/18 Javascript
angular2使用简单介绍
2016/03/01 Javascript
JS实现n秒后自动跳转的两种方法
2020/11/30 Javascript
Bootstrap被封装的弹层
2016/07/20 Javascript
JavaScript中Number对象的toFixed() 方法详解
2016/09/02 Javascript
使用vue.js实现联动效果的示例代码
2017/01/10 Javascript
jQuery插件版本冲突的处理方法分析
2017/01/16 Javascript
深入浅析Vue不同场景下组件间的数据交流
2017/08/15 Javascript
jquery鼠标悬停导航下划线滑出效果
2017/09/29 jQuery
Vue-input框checkbox强制刷新问题
2019/04/18 Javascript
layer弹出层显示在top顶层的方法
2019/09/11 Javascript
Vue v-for循环之@click点击事件获取元素示例
2019/11/09 Javascript
vue图片裁剪插件vue-cropper使用方法详解
2020/12/16 Vue.js
[40:16]TFT vs Mski Supermajor小组赛C组 BO3 第二场 6.3
2018/06/04 DOTA
python3实现磁盘空间监控
2018/06/21 Python
python开发游戏的前期准备
2019/05/05 Python
Python能做什么
2020/06/02 Python
The Hut英国:英国领先的豪华在线百货商店
2019/07/26 全球购物
德国亚马逊官方网站:Amazon.de
2020/11/15 全球购物
总经理助理的八要求
2013/11/12 职场文书
经贸日语专业个人求职信范文
2013/12/28 职场文书
文明村创建实施方案
2014/03/27 职场文书
小学竞选班长演讲稿
2014/09/09 职场文书
中学团支部工作总结
2015/08/13 职场文书
公安干警正风肃纪心得体会
2016/01/15 职场文书
2019行政前台转正申请书范文3篇
2019/08/15 职场文书
python3中apply函数和lambda函数的使用详解
2022/02/28 Python
CSS 左边固定宽右边自适应的6种方法
2022/05/15 HTML / CSS