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发送Email方法实例
Aug 21 Python
Python写的服务监控程序实例
Jan 31 Python
简单介绍Ruby中的CGI编程
Apr 10 Python
python turtle库画一个方格和圆实例
Jun 27 Python
Python3操作Excel文件(读写)的简单实例
Sep 02 Python
下载官网python并安装的步骤详解
Oct 12 Python
python web框架Flask实现图形验证码及验证码的动态刷新实例
Oct 14 Python
python的scipy实现插值的示例代码
Nov 12 Python
Python中实现输入超时及如何通过变量获取变量名
Jan 18 Python
Python IDLE或shell中切换路径的操作
Mar 09 Python
Pycharm Available Package无法显示/安装包的问题Error Loading Package List解决
Sep 18 Python
Python中 range | np.arange | np.linspace三者的区别
Mar 22 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之第二天
2006/10/09 PHP
浅析php变量作用域的一些问题
2013/08/08 PHP
php开发中的页面跳转方法总结
2015/04/26 PHP
twig模板获取全局变量的方法
2016/02/05 PHP
php多进程中的阻塞与非阻塞操作实例分析
2020/03/04 PHP
javascript编程起步(第五课)
2007/02/27 Javascript
Javascript 面向对象之重载
2010/05/04 Javascript
JavaScript高级程序设计 读书笔记之九 本地对象Array
2012/02/27 Javascript
js点击出现悬浮窗效果不使用JQuery插件
2014/01/20 Javascript
jQuery中next()方法用法实例
2015/01/07 Javascript
javascript实现数独解法
2015/03/14 Javascript
jquery预加载图片的方法
2015/05/27 Javascript
WordPress中利用AJAX异步获取评论用户头像的方法
2016/01/08 Javascript
seajs模块之间依赖的加载以及模块的执行
2016/10/21 Javascript
bootstrap日历插件datetimepicker使用方法
2016/12/14 Javascript
react router 4.0以上的路由应用详解
2017/09/21 Javascript
vue 实现剪裁图片并上传服务器功能
2018/03/01 Javascript
详解vue-router导航守卫
2019/01/19 Javascript
详解vue中的父子传值双向绑定及数据更新问题
2019/06/13 Javascript
axios如何取消重复无用的请求详解
2019/12/15 Javascript
vue 项目中当访问路由不存在的时候默认访问404页面操作
2020/08/31 Javascript
全局安装 Vue cli3 和 继续使用 Vue-cli2.x操作
2020/09/08 Javascript
Vue中添加滚动事件设置的方法详解
2020/09/14 Javascript
Python简单删除目录下文件以及文件夹的方法
2015/05/27 Python
浅谈Python中的私有变量
2018/02/28 Python
Python切片操作深入详解
2018/07/27 Python
python实现邮件发送功能
2019/08/10 Python
Django+boostrap 美化admin后台的操作
2020/03/11 Python
Python基于DB-API操作MySQL数据库过程解析
2020/04/23 Python
pandas dataframe 中的explode函数用法详解
2020/05/18 Python
Python configparser模块封装及构造配置文件
2020/08/07 Python
安装Anaconda3及使用Jupyter的方法
2020/10/27 Python
就业自我评价
2014/02/04 职场文书
学生打架检讨书
2014/02/14 职场文书
使用 JavaScript 制作页面效果
2021/04/21 Javascript
python not运算符的实例用法
2021/06/30 Python