堆排序(python实现)
堆排序是利用最大最或最小堆,废话不多说:
先给出几个概念:
二叉树:二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”
完全二叉树:除最后一层外,每一层上的节点数均达到最大值;在最后一层上只缺少右边的若干结点。
满二叉树: 除最后一层无任何子节点外,每一层上的所有结点都有两个子结点。
堆:堆是一种数据结构,类似树根结构,如图,但是不一定是二叉树。
二叉堆:二叉堆是一种特殊的堆,二叉堆是完全二元树(二叉树)或者是近似完全二元树(二叉树),包括最大堆和最小堆。
最大堆:父结点的键值总是大于或等于任何一个子节点的键值,即根节点为最大数字
最小堆:父结点的键值总是大于或等于任何一个子节点的键值,即根节点为最小数字
堆排序步骤:
1.将数据构建成堆,这里的堆指完全二叉树(不一定是满二叉树)
2.将堆调整为最小堆或最大堆
3.此时堆顶已经为最大数或最小数,可以对下面的分支堆再进行调堆即可,此处采用的是将堆顶数取出,再调堆
本人愚钝,网上代码不慎明了,根据自己的思路写了一下,不足之处,请多多指教
1.首先实现将数组按照堆打印
def PrintArrayTree(arr):
frontRowSum=1 #Number of digits in front of n-1 rows
row=1 #row n(start from 1)
for i in range(0,len(arr)):
if i==frontRowSum:
frontRowSum=frontRowSum+2**row #Number of digits in front of n rows
print("\n")#the next row
row=row+1
print (arr[i],end=" ") #print digits
print("Over") arr=[10,9,8,7,6,5,4,3,2,1,234,562,452,23623,565,5,26]
PrintArrayTree(arr)
运行结果如下:
10
9 8
7 6 5 4
3 2 1 234 562 452 23623 565
5 26
print Over
2.构建完了堆,我想实现在堆内任意查找,找到他的子节点和父节点,代码如下:
def FindNode(arr,row,cloumn): if row<1 or cloumn<1:
print("the number of row and column must be greater than 1")
return
if cloumn>2**(row-1):
print("this row just ",2**(row-1),"numbers")
return frontRowSum=0
CurrentRowSum=0
for index in range(0,row-1):
CurrentRowSum=2**index #the number of digits in current row
frontRowSum=frontRowSum+CurrentRowSum #the number of digits of all rows
NodeIndex=frontRowSum+cloumn-1 #find the location of the node in the array by row and cloumn if NodeIndex>len(arr)-1:
print("out of this array")
return currentNode=arr[NodeIndex] childIndex=NodeIndex*2+1 print("Current Node:",currentNode) if row==1: #row 1 have no parent node
print("no parent node!")
else: #the parent node ofcurrent node
parentIndex=int((NodeIndex-1)/2)
parentNode=arr[parentIndex]
print("Parent Node:",parentNode) if childIndex+1>len(arr): #print leftChild node
print("no left child node!")
else:
leftChild=arr[childIndex]
print("Left Child Node:",leftChild) if childIndex+1+1>len(arr): #print rightChild node
print("no left right node!")
else:
rightChild=arr[childIndex+1]
print("Right Child Node:",rightChild) print("\n") arr=[10,9,8,7,6,5,4,3,2,1,234,562,452,23623,565,5,26]
FindNode(arr,1,1)
FindNode(arr,2,2)
FindNode(arr,4,1)
代码运行结果如下:
Current Node: 10
no parent node!
Left Child Node: 9
Right Child Node: 8
Current Node: 8
Parent Node: 10
Left Child Node: 5
Right Child Node: 4
Current Node: 3
Parent Node: 7
Left Child Node: 5
Right Child Node: 26
此代码在堆排序中没有直接用到,但是提供了一些思路
3.按照堆排序步骤,建堆之后需要进行堆调整,接下来进行堆调整,先实现单个叉(某个节点及其子孩子)的进行排序,直接借鉴FindNode里面的代码,将当前节点分别与其左右孩子比较就行了,本文意在实现最小堆,即将小的节点作为父节点
def MinSort(arr,row,cloumn): if row<1 or cloumn<1:
print("the number of row and column must be greater than 1")
return
if cloumn>2**(row-1):
print("this row just ",2**(row-1),"numbers")
return frontRowSum=0
CurrentRowSum=0
for index in range(0,row-1):
CurrentRowSum=2**index #the number of digits in current row
frontRowSum=frontRowSum+CurrentRowSum #the number of digits of all rows
NodeIndex=frontRowSum+cloumn-1 #find the location of the node in the array by row and cloumn if NodeIndex>len(arr)-1:
print("out of this array")
return currentNode=arr[NodeIndex] childIndex=NodeIndex*2+1 print("Current Node:",currentNode) if row==1:
print("no parent node!")
else:
parentIndex=int((NodeIndex-1)/2)
parentNode=arr[parentIndex]
print("Parent Node:",parentNode) if childIndex+1>len(arr):
print("no left child node!")
else:
leftChild=arr[childIndex]
print("Left Child Node:",leftChild) if currentNode>leftChild:
print("swap currentNode and leftChild")
temp=currentNode
currentNode=leftChild
leftChild=temp
arr[childIndex]=leftChild if childIndex+1>=len(arr):
print("no right child node!")
else:
rightChild=arr[childIndex+1] print("Right Chile Node:",rightChild) if currentNode>rightChild:
print("swap rightCild and leftChild")
temp=rightChild
rightChild=currentNode
currentNode=temp
arr[childIndex+1]=rightChild arr[NodeIndex]=currentNode arr=[10,9,8,7,6,5,4,3,2,1,234,562,452,23623,565,5,26]
print("initial array:",arr)
MinSort(arr,1,1)
print("result array:",arr)
运行结果如下,可以看出对于第一个节点,其自孩子为9,8,已经实现将节点与最小的自孩子进行交换,保证父节点小于任何一个子孩子
initial array: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 234, 562, 452, 23623, 565, 5, 26]
Current Node: 10
no parent node!
Left Child Node: 9
swap currentNode and leftChild
Right Chile Node: 8
swap rightCild and leftChild
result array: [8, 10, 9, 7, 6, 5, 4, 3, 2, 1, 234, 562, 452, 23623, 565, 5, 26]
4.已经实现对单个节点和子孩子进行比较,保证父节点小于孩子,将堆内所有拥有孩子的节点进行排序,即可调整为最小堆,代码如下:
def MinHeap(arr): frontRowSum=1
row=1
for i in range(0,len(arr)):
if i==frontRowSum:
frontRowSum=frontRowSum+2**row #the number of digits of all rows
print("\n") # next row
row=row+1
print (arr[i],end=" ")
print("row",row) rowIndex=row-1 #the last row have no child node
print("rowIndex",rowIndex) column=2**(rowIndex-1) #the number of digits of current row print("column",column) number=len(arr) while rowIndex>0: #sort the nodes that have child nodes from the last number to the first number
if number<=2**(rowIndex-1):
rowIndex=rowIndex-1
column=2**(rowIndex-1) print("sort",rowIndex,column)
MinSort(arr,rowIndex,column) number=number-1 column=column-1 arr=[10,9,8,7,6,5,4,3,2,1,234,562,452,23623,565,5,26]
print("initial array:",arr)
PrintArrayTree(arr)
MinHeap(arr)
print("result array:",arr)
PrintArrayTree(arr)
运行结果如下,可以看到最小数字已经位于顶端,实现最小堆
initial array: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 234, 562, 452, 23623, 565, 5, 26]
10
9 8
7 6 5 4
3 2 1 234 562 452 23623 565
5 26
print Over
.......
result array: [1, 10, 4, 9, 2, 8, 5, 7, 3, 6, 234, 562, 452, 23623, 565, 5, 26]
1
10 4
9 2 8 5
7 3 6 234 562 452 23623 565
5 26
print Over
4.最小值已经到顶端,将最小值依次取出,然后再调整堆,再取出,就完成堆排序。代码如下:
def HeapSort(arr):
arr2=[]
for i in range(0,len(arr)):
MinHeap(arr)
arr2.append(arr[0])
del arr[0]
return arr2 arr=[10,9,8,7,6,5,4,3,2,1,234,562,452,23623,565,5,26]
print("initial array:",arr)
PrintArrayTree(arr)
resultArr=HeapSort(arr)
print("result array:",resultArr)
PrintArrayTree(resultArr)
运行结果如下:
initial array: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 234, 562, 452, 23623, 565, 5, 26]
10
9 8
7 6 5 4
3 2 1 234 562 452 23623 565
5 26
print Over
10
9 8
7 6 5 4
3 2 1 234 562 452 23623 565
5 26
.........
result array: [1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10, 26, 234, 452, 562, 565, 23623]
1
2 3
4 5 5 6
7 8 9 10 26 234 452 562
565 23623
print Over
5.后续工作:
1)代码需要优化
2)感觉堆排序有点类似冒泡排序
3)需要检查代码的健壮性
4)后续需要计算分析代码的复杂度
1)优化之后的程序如下:写法还能再优化,但继续优化会影响可读性
def MinSort(arr,start,end):
import math
arrHeight=0
for index in range(0,end-start):
if index==2**(arrHeight+1)-1:
arrHeight=arrHeight+1 for NodeIndex in range(2**(arrHeight)-2,-1,-1):
currentNode=arr[NodeIndex+start]
childIndex=NodeIndex*2+1+start if childIndex+1>len(arr):
continue
else:
leftChild=arr[childIndex] if currentNode>leftChild:
temp=currentNode
currentNode=leftChild
leftChild=temp
arr[childIndex]=leftChild
arr[NodeIndex+start]=currentNode if childIndex+1>=len(arr):
continue
else:
rightChild=arr[childIndex+1]
if currentNode>rightChild: temp=rightChild
rightChild=currentNode
currentNode=temp
arr[childIndex+1]=rightChild
arr[NodeIndex+start]=currentNode def HeapSort(arr):
for i in range(0,len(arr)-1):
MinSort(arr,i,len(arr)) arr=[10,9,8,7,6,5,4,3,2,1,234,562,452,23623,565,5,26] print("Initial array:\n",arr)
HeapSort(arr)
print("Result array:\n",arr)
运行结果:
Initial array:
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 234, 562, 452, 23623, 565, 5, 26]
Result array:
[1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10, 26, 234, 452, 562, 565, 23623]
堆排序(python实现)的更多相关文章
- 高速排序,归并排序,堆排序python实现
高速排序的时间复杂度最好情况下为O(n*logn),最坏情况下为O(n^2),平均情况下为O(n*logn),是不稳定的排序 归并排序的时间复杂度最好情况下为O(n*logn),最坏情况下为O(n*l ...
- 堆排序python实现
def MAX_Heapify(heap,HeapSize,root):#在堆中做结构调整使得父节点的值大于子节点 left = 2*root+1 right = left + 1 larger = ...
- 简单的堆排序-python
AA = raw_input().strip().split(' ') A = [] ###############初始化大堆############### def fixUp(A): k = len ...
- 排序NB三人组
排序NB三人组 快速排序,堆排序,归并排序 1.快速排序 方法其实很简单:分别从初始序列“6 1 2 7 9 3 4 5 10 8”两端开始“探测”.先从右往左找一个小于6的数,再从左往 ...
- 3、计数排序,电影top100
1.计数排序 # -*- coding: utf-8 -*- # @Time : 2018/07/31 0031 11:32 # @Author : Venicid def count_sort(li ...
- 数据结构:堆排序 (python版) 小顶堆实现从大到小排序 | 大顶堆实现从小到大排序
#!/usr/bin/env python # -*- coding:utf-8 -*- ''' Author: Minion-Xu 小堆序实现从大到小排序,大堆序实现从小到大排序 重点的地方:小堆序 ...
- 你需要知道的九大排序算法【Python实现】之堆排序
六.堆排序 堆排序是一种树形选择排序,是对直接选择排序的有效改进. 堆的定义下:具有n个元素的序列 (h1,h2,...,hn),当且仅当满足(hi>=h2i,hi>=2i+1)或(h ...
- python下实现二叉堆以及堆排序
python下实现二叉堆以及堆排序 堆是一种特殊的树形结构, 堆中的数据存储满足一定的堆序.堆排序是一种选择排序, 其算法复杂度, 时间复杂度相对于其他的排序算法都有很大的优势. 堆分为大头堆和小头堆 ...
- 算法导论 第六章 堆排序(python)
6.1堆 卫星数据:一个带排序的的数通常是有一个称为记录的数据集组成的,每一个记录有一个关键字key,记录的其他数据称为卫星数据. 原地排序:在排序输入数组时,只有常数个元素被存放到数组以外的空间中去 ...
- Python八大算法的实现,插入排序、希尔排序、冒泡排序、快速排序、直接选择排序、堆排序、归并排序、基数排序。
Python八大算法的实现,插入排序.希尔排序.冒泡排序.快速排序.直接选择排序.堆排序.归并排序.基数排序. 1.插入排序 描述 插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得 ...
随机推荐
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(22)-权限管理系统-模块导航制作
系列目录 最近比较忙,系统难度独步增加,文章的发布速度明显比以前慢了. 由于我们已经跑通了整个系统,所有东西都回到了简单,接下来我们做模块制作也就是操作SysModule表. 首先我们来回顾一下之前的 ...
- ASP.NET Core的配置(5):配置的同步[设计篇]
本节所谓的"配置同步"主要体现在两个方面:其一,如何监控配置源并在其变化的时候自动加载其数据,其目的是让应用中通过Configuration对象承载的配置与配置源的数据同步:其二. ...
- 应用新安全组 - 每天5分钟玩转 OpenStack(116)
Neutron 默认的安全组规则会禁止掉所有从外面访问 instance 的流量. 本节我们会修改安全组的配置,允许 ping 和 ssh instance.有两种方法可以达到这个目的: 1. 修改 ...
- geotrellis使用(二十三)动态加载时间序列数据
目录 前言 实现方法 总结 一.前言 今天要介绍的绝对是华丽的干货.比如我们从互联网上下载到了一系列(每天或者月平均等)的MODIS数据,我们怎么能够对比同一区域不同时间的数据情况,采用 ...
- linux内核调试技术之自构proc
1.简介 在上一篇中,在内核中使用printk可以讲调试信息保存在log_buf缓冲区中,可以使用命令 #cat /proc/kmsg 将缓冲区的数区的数数据打印出来,今天我们就来研究一下,自己写k ...
- [Servlet] 初识Servlet
什么是Servlet? 定义 Servlet的全称是 Server Applet,顾名思义,就是用 Java 编写的服务器端程序. Servlet 是一个 Java Web开发标准,狭义的Servle ...
- .net请求URL过长,解决方案
<system.web> 节点下加上 <httpRuntime requestValidationMode="2.0" maxQueryStringLength= ...
- 项目积累(三)CSS
公司不是专门做网站的,偶尔会接到客户让修改前端,有时候和让头疼,自己浏览器兼容问题处理不好. 慢慢积累吧. 先贴出来一些前端代码吧,如下: <div class="test" ...
- 打造高效前端工作环境-tmuxinator
前言 虽然tmux能让我们方便组织工作环境,但每次重新打开会话时都需要手动重新创建窗口.窗格和执行各种程序,能不能像VS那样以工程为单位保存窗口.窗格和各种所需执行的程序的信息呢?tmuxinato ...
- Salesforce的sharing Rule 不支持Lookup型字段解决方案
Salesforce 中 sharing rule 并不支持Look up 字段 和 formula 字段.但在实际项目中,有时会需要在sharing rule中直接取Look up型字段的值,解决方 ...