堆排序是利用最大最或最小堆,废话不多说:

先给出几个概念:

二叉树:二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(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实现)相关推荐

  1. 堆排序-Python

    堆排序-Python python代码 python代码 def build_heap(array):for i in range(len(array)//2-1,-1,-1):big_heap(ar ...

  2. 堆排序python代码实现_python实现堆排序

    首先理解堆排序: 堆: 堆栈是计算机的两种最基本的数据结构.堆的特点就是FIFO(first in first out)先进先出,这里的话我觉得可以理解成树的结构.堆在接收数据的时候先接收的数据会被先 ...

  3. Python天天美味(32) - python数据结构与算法之堆排序

    1. 选择排序 选择排序原理是先选出最小的数,与第一个数交换,然后从第二个数开始再选择最小的数与第二个数交换,-- def selection_sort(data):     for i in ran ...

  4. python中堆排序_Python实现堆排序的方法详解

    本文实例讲述了Python实现堆排序的方法.分享给大家供大家参考,具体如下: 堆排序作是基本排序方法的一种,类似于合并排序而不像插入排序,它的运行时间为O(nlogn),像插入排序而不像合并排序,它是 ...

  5. [转载] python实现堆排序用类的方法_python实现堆排序的实例讲解

    参考链接: 用Python进行堆排序heap sort 堆排序 堆是一种完全二叉树(是除了最后一层,其它每一层都被完全填充,保持所有节点都向左对齐),首先需要知道概念:最大堆问题,最大堆就是根节点比子 ...

  6. Python天天美味(35) - 细品lambda

    lambda函数也叫匿名函数,即,函数没有具体的名称.先来看一个最简单例子: def f(x):     return x**2 print f(4) Python中使用lambda的话,写成这样 g ...

  7. python语言做法_python学习笔记(十六)

    ## Python语言进阶 ### 重要知识点 - 生成式(推导式)的用法 ```Python prices = { 'AAPL': 191.88, 'GOOG': 1186.96, 'IBM': 1 ...

  8. python 判断div 之间的内容是否为空_python实现数据结构与算法之双端队列实现

    简介 双端队列(deque, double-ended queue),是一种具有队列和栈的性质的数据结构.双端队列中的元素可以从两端弹出,其限定插入和删除操作在表的两端进行.双端队列可以在队列任意一端 ...

  9. Python天天美味(35) - 细品lambda(转)

    lambda函数也叫匿名函数,即,函数没有具体的名称.先来看一个最简单例子: def f(x):     return x**2 print f(4) Python中使用lambda的话,写成这样 g ...

  10. python学习之旅_第2天

    学习目标: 三天掌握 python 入门知识 学习内容: 1. Python3 迭代器与生成器 2. Python3 函数 3. Python3 数据结构 4. Python3 模块 5. Pytho ...

最新文章

  1. Nature综述——真菌的多样性:真菌的高通量测序及鉴定
  2. 2018年『web』开发者不得不知的技术趋势
  3. 《Windows CE大排档》第一版勘误表
  4. linux装oracle11g启动失败,Oracle11GSELinux原因启动失败的解决办法
  5. java多线程runnable_Java 多线程 之 Runnable
  6. ASP.Net网站部署失败
  7. JdbcTemplate(操作数据库-查询返回对象、查询返回集合)
  8. 【Java】对JTable里的元素进行排序
  9. 位运算在一类数组题中的用法 只出现一次的数字I
  10. 通过历史控制文件恢复Oracle数据库,只需这10步
  11. 用python批量下载modis数据的速度怎么样_MODIS数据的简介和下载(五)——应用密钥的Python脚本下载...
  12. 华为机试HJ90:合法IP
  13. 数据挖掘原理与算法_古今争翘,一首机器学习与数据挖掘神曲,共11.99G送你直上云霄...
  14. 写代码不严谨,我就不配当程序员?
  15. 蔡学镛:让架构接地气,不再云里雾里
  16. 初学java之家庭记账系统
  17. 光纤信号服务器,485转光纤的两种方式
  18. 修改网络设备在路由器中显示名称
  19. 如何更改计算机用户账户和密码,怎么修改电脑用户账户
  20. java导航网站_java导航网站

热门文章

  1. git 常见操作合集
  2. 服务器 --- 开发框架
  3. redis分布式锁的 5个坑
  4. android 登录qq接口开发,三方登录-QQ登录开发-Android(as版本)
  5. python 普通人能做什么-普通人学Python有什么用?
  6. mysql离线安装 window_5分钟完成mysql离线安装
  7. 【渝粤教育】国家开放大学2018年春季 8638-21T薪酬制度与薪酬管理 参考试题
  8. 【渝粤教育】国家开放大学2018年春季 0281-22T色装概论 参考试题
  9. 深度学习系列(三)【人类语言处理--语音转换】
  10. 先安装windows7_64bit,再安装Centos7,windows7的启动项不出现