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常见文件操作的函数示例代码
Nov 15 Python
python处理PHP数组文本文件实例
Sep 18 Python
python实现基于两张图片生成圆角图标效果的方法
Mar 26 Python
python类的方法属性与方法属性的动态绑定代码详解
Dec 27 Python
解决Pycharm无法import自己安装的第三方module问题
May 18 Python
python添加模块搜索路径和包的导入方法
Jan 19 Python
python的pstuil模块使用方法总结
Jul 26 Python
django基于存储在前端的token用户认证解析
Aug 06 Python
python的命名规则知识点总结
Oct 04 Python
python except异常处理之后不退出,解决异常继续执行的实现
Apr 25 Python
python 用opencv实现霍夫线变换
Nov 27 Python
Python中异常处理用法
Nov 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
如何冲泡挂耳包咖啡?技巧是什么
2021/03/04 冲泡冲煮
php基于curl实现随机ip地址抓取内容的方法
2016/10/11 PHP
php计数排序算法的实现代码(附四个实例代码)
2020/03/31 PHP
javascript 当前日期转化为中文的实现代码
2010/05/13 Javascript
JavaScrip单线程引擎工作原理分析
2010/09/04 Javascript
JavaScript对象和字串之间的转换实例探讨
2013/04/21 Javascript
浅析JQuery UI Dialog的样式设置问题
2013/12/18 Javascript
Jquery选择器中使用变量实现动态选择例子
2014/07/25 Javascript
详解Jquery实现ready和bind事件
2016/04/14 Javascript
a标签跳转到指定div,jquery添加和移除class属性的实现方法
2016/10/10 Javascript
Angular2学习教程之ng中变更检测问题详解
2017/05/28 Javascript
浅谈在koa2中实现页面渲染的全局数据
2017/10/09 Javascript
node中间层实现文件上传功能
2018/06/11 Javascript
Vue中插入HTML代码的方法
2018/09/21 Javascript
js实现图片推拉门效果代码实例
2019/05/18 Javascript
JavaScript进阶(三)闭包原理与用法详解
2020/05/09 Javascript
vue中element 的upload组件发送请求给后端操作
2020/09/07 Javascript
关于javascript中的promise的用法和注意事项(推荐)
2021/01/15 Javascript
使用Python中的greenlet包实现并发编程的入门教程
2015/04/16 Python
在Django的模板中使用认证数据的方法
2015/07/23 Python
浅谈python中的数字类型与处理工具
2017/08/02 Python
Python读取txt文件数据的方法(用于接口自动化参数化数据)
2018/06/27 Python
Python多继承原理与用法示例
2018/08/23 Python
python实现换位加密算法的示例
2018/10/14 Python
解决pycharm安装后代码区不能编辑的问题
2018/10/28 Python
浅谈pytorch torch.backends.cudnn设置作用
2020/02/20 Python
实例教程 利用html5和css3打造一款创意404页面
2014/10/20 HTML / CSS
世界上最大的餐具公司:Oneida
2016/12/17 全球购物
域名注册、建站工具、网页主机、SSL证书:Dynadot
2017/01/06 全球购物
世界上最大的皮肤科医生拥有和经营的美容网站:LovelySkin
2021/01/03 全球购物
沃尔玛旗下墨西哥超市:Bodega Aurrera
2020/11/13 全球购物
构造方法和其他方法的区别?怎么调用父类的构造方法
2013/09/22 面试题
酒店总经理欢迎词
2014/01/15 职场文书
《商鞅南门立木》教学反思
2014/02/16 职场文书
文艺演出策划方案
2014/06/07 职场文书
测量JavaScript函数的性能各种方式对比
2021/04/27 Javascript