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使用webbrowser浏览指定url的方法
Apr 04 Python
小议Python中自定义函数的可变参数的使用及注意点
Jun 21 Python
Python中用post、get方式提交数据的方法示例
Sep 22 Python
python  创建一个保留重复值的列表的补码
Oct 15 Python
Python使用pydub库对mp3与wav格式进行互转的方法
Jan 10 Python
python通过配置文件共享全局变量的实例
Jan 11 Python
numpy 声明空数组详解
Dec 05 Python
Jupyter Notebook输出矢量图实例
Apr 14 Python
Python图像识别+KNN求解数独的实现
Nov 13 Python
python模拟点击玩游戏的实例讲解
Nov 26 Python
java关于string最常出现的面试题整理
Jan 18 Python
Python中可变和不可变对象的深入讲解
Aug 02 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 输出简单动态WAP页面
2009/06/09 PHP
php cc攻击代码与防范方法
2012/10/18 PHP
JavaScript中的new的使用方法与注意事项
2007/05/16 Javascript
查询绑定数据岛的表格中的文本并修改显示方式的js代码
2009/12/15 Javascript
jQuery ajax BUG:object doesn't support this property or method
2010/07/06 Javascript
jQuery编辑器KindEditor4.1.4代码高亮显示设置教程
2013/03/01 Javascript
iframe如何动态创建及释放其所占内存
2014/09/03 Javascript
以WordPress为例讲解jQuery美化页面Title的方法
2016/05/23 Javascript
JS 中document.write()的用法和清空的原因浅析
2017/12/04 Javascript
Angularjs过滤器实现动态搜索与排序功能示例
2017/12/13 Javascript
vue axios 在页面切换时中断请求方法 ajax
2018/03/05 Javascript
React Hooks的深入理解与使用
2018/11/12 Javascript
微信小程序获取用户openid的实现
2018/12/24 Javascript
详解Vue.js v-for不支持IE9的解决方法
2018/12/29 Javascript
vue 进阶之实现父子组件间的传值
2019/04/26 Javascript
javascript/jquery实现点击触发事件的方法分析
2019/11/11 jQuery
vue路由跳转传递参数的方式总结
2020/05/10 Javascript
jQuery实现简单全选框
2020/09/13 jQuery
Javascript中的奇葩知识,你知道吗?
2021/01/25 Javascript
基python实现多线程网页爬虫
2015/09/06 Python
解决python3 urllib中urlopen报错的问题
2017/03/25 Python
python实现快速排序的示例(二分法思想)
2018/03/12 Python
Pandas时间序列:重采样及频率转换方式
2019/12/26 Python
python 使用递归实现打印一个数字的每一位示例
2020/02/27 Python
理解Django 中Call Stack机制的小Demo
2020/09/01 Python
Python爬虫设置Cookie解决网站拦截并爬取蚂蚁短租的问题
2021/02/22 Python
Mixbook加拿大:照片书,照片卡,剪贴簿,年历和日历
2017/02/21 全球购物
Tostadora意大利:定制T恤
2019/04/08 全球购物
英国时尚首饰品牌:Missoma
2020/06/29 全球购物
vue路由实现登录拦截
2021/03/24 Vue.js
医科大学生毕业的自我评价分享
2013/11/12 职场文书
法人代表委托书
2014/04/04 职场文书
小学清明节活动总结
2014/07/04 职场文书
支教个人总结
2015/03/04 职场文书
黑白记忆观后感
2015/06/18 职场文书
2016大学生社会实践单位评语
2015/12/01 职场文书