堆排序(python实现)
堆排序是利用最大最或最小堆,废话不多说:
先给出几个概念:
二叉树:二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”
完全二叉树:除最后一层外,每一层上的节点数均达到最大值;在最后一层上只缺少右边的若干结点。
满二叉树: 除最后一层无任何子节点外,每一层上的所有结点都有两个子结点。
堆:堆是一种数据结构,类似树根结构,如图,但是不一定是二叉树。
二叉堆:二叉堆是一种特殊的堆,二叉堆是完全二元树(二叉树)或者是近似完全二元树(二叉树),包括最大堆和最小堆。
最大堆:父结点的键值总是大于或等于任何一个子节点的键值,即根节点为最大数字
最小堆:父结点的键值总是大于或等于任何一个子节点的键值,即根节点为最小数字
堆排序步骤:
1.将数据构建成堆,这里的堆指完全二叉树(不一定是满二叉树)
2.将堆调整为最小堆或最大堆
3.此时堆顶已经为最大数或最小数,可以对下面的分支堆再进行调堆即可,此处采用的是将堆顶数取出,再调堆
本人愚钝,网上代码不慎明了,根据自己的思路写了一下,不足之处,请多多指教
1.首先实现将数组按照堆打印
1 def PrintArrayTree(arr): 2 frontRowSum=1 #Number of digits in front of n-1 rows 3 row=1 #row n(start from 1) 4 for i in range(0,len(arr)): 5 if i==frontRowSum: 6 frontRowSum=frontRowSum+2**row #Number of digits in front of n rows 7 print("\n")#the next row 8 row=row+1 9 print (arr[i],end=" ") #print digits 10 print("Over") 11 12 arr=[10,9,8,7,6,5,4,3,2,1,234,562,452,23623,565,5,26] 13 PrintArrayTree(arr)
运行结果如下:
10
9 8
7 6 5 4
3 2 1 234 562 452 23623 565
5 26
print Over
2.构建完了堆,我想实现在堆内任意查找,找到他的子节点和父节点,代码如下:
1 def FindNode(arr,row,cloumn): 2 3 if row<1 or cloumn<1: 4 print("the number of row and column must be greater than 1") 5 return 6 if cloumn>2**(row-1): 7 print("this row just ",2**(row-1),"numbers") 8 return 9 10 frontRowSum=0 11 CurrentRowSum=0 12 for index in range(0,row-1): 13 CurrentRowSum=2**index #the number of digits in current row 14 frontRowSum=frontRowSum+CurrentRowSum #the number of digits of all rows 15 NodeIndex=frontRowSum+cloumn-1 #find the location of the node in the array by row and cloumn 16 17 if NodeIndex>len(arr)-1: 18 print("out of this array") 19 return 20 21 currentNode=arr[NodeIndex] 22 23 childIndex=NodeIndex*2+1 24 25 print("Current Node:",currentNode) 26 27 if row==1: #row 1 have no parent node 28 print("no parent node!") 29 else: #the parent node ofcurrent node 30 parentIndex=int((NodeIndex-1)/2) 31 parentNode=arr[parentIndex] 32 print("Parent Node:",parentNode) 33 34 if childIndex+1>len(arr): #print leftChild node 35 print("no left child node!") 36 else: 37 leftChild=arr[childIndex] 38 print("Left Child Node:",leftChild) 39 40 41 if childIndex+1+1>len(arr): #print rightChild node 42 print("no left right node!") 43 else: 44 rightChild=arr[childIndex+1] 45 print("Right Child Node:",rightChild) 46 47 print("\n") 48 49 arr=[10,9,8,7,6,5,4,3,2,1,234,562,452,23623,565,5,26] 50 FindNode(arr,1,1) 51 FindNode(arr,2,2) 52 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")returnif cloumn>2**(row-1):print("this row just ",2**(row-1),"numbers")returnfrontRowSum=0CurrentRowSum=0for index in range(0,row-1): CurrentRowSum=2**index #the number of digits in current rowfrontRowSum=frontRowSum+CurrentRowSum #the number of digits of all rowsNodeIndex=frontRowSum+cloumn-1 #find the location of the node in the array by row and cloumnif NodeIndex>len(arr)-1:print("out of this array")returncurrentNode=arr[NodeIndex]childIndex=NodeIndex*2+1print("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=currentNodecurrentNode=leftChildleftChild=temparr[childIndex]=leftChildif 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=rightChildrightChild=currentNodecurrentNode=temparr[childIndex+1]=rightChildarr[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=1row=1for i in range(0,len(arr)):if i==frontRowSum:frontRowSum=frontRowSum+2**row #the number of digits of all rowsprint("\n") # next rowrow=row+1print (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 rowprint("column",column)number=len(arr)while rowIndex>0: #sort the nodes that have child nodes from the last number to the first numberif number<=2**(rowIndex-1):rowIndex=rowIndex-1column=2**(rowIndex-1)print("sort",rowIndex,column)MinSort(arr,rowIndex,column)number=number-1column=column-1arr=[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.最小值已经到顶端,将最小值依次取出,然后再调整堆,再取出,就完成堆排序。代码如下:
1 def HeapSort(arr): 2 arr2=[] 3 for i in range(0,len(arr)): 4 MinHeap(arr) 5 arr2.append(arr[0]) 6 del arr[0] 7 return arr2 8 9 arr=[10,9,8,7,6,5,4,3,2,1,234,562,452,23623,565,5,26] 10 print("initial array:",arr) 11 PrintArrayTree(arr) 12 resultArr=HeapSort(arr) 13 print("result array:",resultArr) 14 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)优化之后的程序如下:写法还能再优化,但继续优化会影响可读性
1 def MinSort(arr,start,end): 2 import math 3 arrHeight=0 4 for index in range(0,end-start): 5 if index==2**(arrHeight+1)-1: 6 arrHeight=arrHeight+1 7 8 for NodeIndex in range(2**(arrHeight)-2,-1,-1): 9 currentNode=arr[NodeIndex+start] 10 childIndex=NodeIndex*2+1+start 11 12 if childIndex+1>len(arr): 13 continue 14 else: 15 leftChild=arr[childIndex] 16 17 if currentNode>leftChild: 18 temp=currentNode 19 currentNode=leftChild 20 leftChild=temp 21 arr[childIndex]=leftChild 22 arr[NodeIndex+start]=currentNode 23 24 if childIndex+1>=len(arr): 25 continue 26 else: 27 rightChild=arr[childIndex+1] 28 if currentNode>rightChild: 29 30 temp=rightChild 31 rightChild=currentNode 32 currentNode=temp 33 arr[childIndex+1]=rightChild 34 arr[NodeIndex+start]=currentNode 35 36 37 def HeapSort(arr): 38 for i in range(0,len(arr)-1): 39 MinSort(arr,i,len(arr)) 40 41 42 arr=[10,9,8,7,6,5,4,3,2,1,234,562,452,23623,565,5,26] 43 44 print("Initial array:\n",arr) 45 HeapSort(arr) 46 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]
转载于:https://www.cnblogs.com/feichangnice/p/5321351.html
堆排序(python实现)相关推荐
- 堆排序-Python
堆排序-Python python代码 python代码 def build_heap(array):for i in range(len(array)//2-1,-1,-1):big_heap(ar ...
- 堆排序python代码实现_python实现堆排序
首先理解堆排序: 堆: 堆栈是计算机的两种最基本的数据结构.堆的特点就是FIFO(first in first out)先进先出,这里的话我觉得可以理解成树的结构.堆在接收数据的时候先接收的数据会被先 ...
- Python天天美味(32) - python数据结构与算法之堆排序
1. 选择排序 选择排序原理是先选出最小的数,与第一个数交换,然后从第二个数开始再选择最小的数与第二个数交换,-- def selection_sort(data): for i in ran ...
- python中堆排序_Python实现堆排序的方法详解
本文实例讲述了Python实现堆排序的方法.分享给大家供大家参考,具体如下: 堆排序作是基本排序方法的一种,类似于合并排序而不像插入排序,它的运行时间为O(nlogn),像插入排序而不像合并排序,它是 ...
- [转载] python实现堆排序用类的方法_python实现堆排序的实例讲解
参考链接: 用Python进行堆排序heap sort 堆排序 堆是一种完全二叉树(是除了最后一层,其它每一层都被完全填充,保持所有节点都向左对齐),首先需要知道概念:最大堆问题,最大堆就是根节点比子 ...
- Python天天美味(35) - 细品lambda
lambda函数也叫匿名函数,即,函数没有具体的名称.先来看一个最简单例子: def f(x): return x**2 print f(4) Python中使用lambda的话,写成这样 g ...
- python语言做法_python学习笔记(十六)
## Python语言进阶 ### 重要知识点 - 生成式(推导式)的用法 ```Python prices = { 'AAPL': 191.88, 'GOOG': 1186.96, 'IBM': 1 ...
- python 判断div 之间的内容是否为空_python实现数据结构与算法之双端队列实现
简介 双端队列(deque, double-ended queue),是一种具有队列和栈的性质的数据结构.双端队列中的元素可以从两端弹出,其限定插入和删除操作在表的两端进行.双端队列可以在队列任意一端 ...
- Python天天美味(35) - 细品lambda(转)
lambda函数也叫匿名函数,即,函数没有具体的名称.先来看一个最简单例子: def f(x): return x**2 print f(4) Python中使用lambda的话,写成这样 g ...
- python学习之旅_第2天
学习目标: 三天掌握 python 入门知识 学习内容: 1. Python3 迭代器与生成器 2. Python3 函数 3. Python3 数据结构 4. Python3 模块 5. Pytho ...
最新文章
- Nature综述——真菌的多样性:真菌的高通量测序及鉴定
- 2018年『web』开发者不得不知的技术趋势
- 《Windows CE大排档》第一版勘误表
- linux装oracle11g启动失败,Oracle11GSELinux原因启动失败的解决办法
- java多线程runnable_Java 多线程 之 Runnable
- ASP.Net网站部署失败
- JdbcTemplate(操作数据库-查询返回对象、查询返回集合)
- 【Java】对JTable里的元素进行排序
- 位运算在一类数组题中的用法 只出现一次的数字I
- 通过历史控制文件恢复Oracle数据库,只需这10步
- 用python批量下载modis数据的速度怎么样_MODIS数据的简介和下载(五)——应用密钥的Python脚本下载...
- 华为机试HJ90:合法IP
- 数据挖掘原理与算法_古今争翘,一首机器学习与数据挖掘神曲,共11.99G送你直上云霄...
- 写代码不严谨,我就不配当程序员?
- 蔡学镛:让架构接地气,不再云里雾里
- 初学java之家庭记账系统
- 光纤信号服务器,485转光纤的两种方式
- 修改网络设备在路由器中显示名称
- 如何更改计算机用户账户和密码,怎么修改电脑用户账户
- java导航网站_java导航网站
热门文章
- git 常见操作合集
- 服务器 --- 开发框架
- redis分布式锁的 5个坑
- android 登录qq接口开发,三方登录-QQ登录开发-Android(as版本)
- python 普通人能做什么-普通人学Python有什么用?
- mysql离线安装 window_5分钟完成mysql离线安装
- 【渝粤教育】国家开放大学2018年春季 8638-21T薪酬制度与薪酬管理 参考试题
- 【渝粤教育】国家开放大学2018年春季 0281-22T色装概论 参考试题
- 深度学习系列(三)【人类语言处理--语音转换】
- 先安装windows7_64bit,再安装Centos7,windows7的启动项不出现