排序 9
来源:互联网 发布:淘宝新店搜索软件 编辑:程序博客网 时间:2024/05/16 15:05
参考:
排序 0 - 前言
百度百科:堆排序
【Python排序搜索基本算法】之堆排序
【坐在马桶上看算法】算法11:堆——神奇的优先队列(上)
【坐在马桶上看算法】算法12:堆——神奇的优先队列(下)
python数据结构之二叉树的实现
堆排序(heap sort)
关键名词
参考:
二叉树
完全二叉树
二叉树:每个节点最多有两个子树的树结构
完全二叉树:叶节点只能出现在最下层和次下层,并且最下面一层的节点都集中在该层最左边的若干位置的二叉树。设树层数为
h
,则1-(h-1)
层的节点数均达到了最大值,而第h
层的节点均集中在最左边- 将完全二叉树的节点值排成列表形式,则第
i
个节点的左右子树为2i
和2i+1
- 将完全二叉树的节点值排成列表形式,则第
堆分为 大根堆 和 小根堆
大根堆:根节点(或称为 堆顶)的值 大于等于 左右子树的完全二叉树
小根堆:根节点(或称为 堆顶)的值 小于等于 左右子树的完全二叉树
工作原理
根据堆的特性,其位于堆顶的值为最大值或者最小值,所以每次取堆顶节点值,删除堆顶节点,重新构建堆,直到堆为空为止,排序完成
算法思想
难点一:如何构建堆
堆既然是完全二叉树,所以可以用序列表示,每次新增加一个节点,将其加入到序列末尾,设为 n
,其根节点位置即为 n // 2
,比较两者的大小,进行替换,依次类推,调整堆的结构
为方便计算,设序列为 [-1, x1, x2, x3, ...]
,其第一个元素 -1
无效,从下标 1
开始计算
难点二:如何删除堆顶后,重新构建堆
删除堆顶后,取序列末尾元素,放在堆顶位置,重新计算堆的结构
对于大根堆来说,每次向下调整时,如果需要交换根和左右子树的值,和左右子树中较大值进行交换
对于小根堆来说,与之相反
思路
获得一个无序序列后,先将其构建成堆结构,然后每次取堆顶元素,重新构建堆,直到堆为空为止
Python 算法实现
实现一:使用一个辅助序列
# -*- coding: utf-8 -*-"""堆排序实现"""import randomimport math__author__ = 'zj'def create_data(leng, min, max): """ 创建待排序序列 :param leng: 序列长度 :param min: 最小值 :param max: 最大值 :return: 列表 """ li = range(min, max) return random.sample(li, leng)def heap_sort_add(heap, v): """ 在堆上加入一个元素 :param heap: 大根堆 :param v: 插入数据 :return: """ heap.append(v) idx = len(heap) - 1 r = idx // 2 while r >= 1: if heap[r] < heap[idx]: heap[r], heap[idx] = heap[idx], heap[r] idx = r r = idx // 2 else: break return heapdef heap_sort_delete(heap): """ 删除堆顶元素 :param heap: 大根堆 :return: """ if len(heap) == 1: return heap elif len(heap) == 2: del heap[0] return heap heap[1] = heap[-1] del heap[-1] n = len(heap) - 1 idx = 1 n = len(heap) while idx < n: lchild = 2 * idx rchild = 2 * idx + 1 if lchild >= n: break elif lchild < n and rchild >= n: if heap[idx] < heap[lchild]: heap[idx], heap[lchild] = heap[lchild], heap[idx] idx = lchild else: break elif lchild < n and rchild < n: if heap[lchild] > heap[rchild]: if heap[idx] < heap[lchild]: heap[idx], heap[lchild] = heap[lchild], heap[idx] idx = lchild else: break else: if heap[idx] < heap[rchild]: heap[idx], heap[rchild] = heap[rchild], heap[idx] idx = rchild else: break return heapdef heap_sort(li, reverse=False): """ 堆排序实现 :param li: 待排序列表 :param reverse: 是否从大到小排序,默认为False :return: 已排序列表 """ src = [0] for item in li: heap_sort_add(src, item) n = len(li) for i in xrange(n): if reverse: li[n - i - 1] = src[1] else: li[i] = src[1] heap_sort_delete(src) return liif __name__ == '__main__': da = create_data(10, 30, 60) print da heap_sort(da) print da
实现二:使用自身序列,实现从小到大排序
# -*- coding: utf-8 -*-"""堆排序实现"""import randomimport math__author__ = 'zj'def create_data(leng, min, max): """ 创建待排序序列 :param leng: 序列长度 :param min: 最小值 :param max: 最大值 :return: 列表 """ li = range(min, max) return random.sample(li, leng)def heap_sort_add_v2(heap, n): """ 堆中加入新数据,下标为 n :param heap: 堆和待排序序列 :param n: 前 n-1 个元素为堆,后面元素为待排序序列 :return: """ idx = n r = idx // 2 while r >= 1: if heap[r] < heap[idx]: heap[r], heap[idx] = heap[idx], heap[r] idx = r r = idx // 2 else: break return heapdef heap_sort_delete_v2(heap, n): """ 删除堆顶元素 :param heap: 大根堆 :return: """ heap[1], heap[n] = heap[n], heap[1] idx = 1 while idx < n: lchild = 2 * idx rchild = 2 * idx + 1 if lchild >= n: break elif lchild < n and rchild >= n: if heap[idx] < heap[lchild]: heap[idx], heap[lchild] = heap[lchild], heap[idx] idx = lchild else: break elif lchild < n and rchild < n: if heap[lchild] > heap[rchild]: if heap[idx] < heap[lchild]: heap[idx], heap[lchild] = heap[lchild], heap[idx] idx = lchild else: break else: if heap[idx] < heap[rchild]: heap[idx], heap[rchild] = heap[rchild], heap[idx] idx = rchild else: break return heapdef heap_sort_v2(li): """ 从小到大排序 :param li: :return: """ li.insert(0, -1) for i in xrange(2, len(li)): heap_sort_add_v2(li, i) for i in range(2, len(li))[::-1]: heap_sort_delete_v2(li, i) del li[0] return liif __name__ == '__main__': da = create_data(10, 30, 60) print da heap_sort_v2(da) print da
性能分析
稳定性
堆排序是不稳定排序算法
在删除堆顶,重新构建堆的过程中,需要将末尾节点元素放置在堆顶,重新构建,这样会破坏相对位置关系
时间复杂度
其时间复杂度为 O(N*logN)
空间复杂度
空间复杂度为 O(1)
- 排序9:归并排序
- 排序9:计数排序
- 排序。9
- 排序 9
- 9种排序算法——堆排序,归并排序,插入排序,选择排序
- 【数据结构之排序9】箱排序
- Java排序算法9:堆排序
- 算法、排序(9)
- 9种排序
- 【一种排序 9】
- (9)选择排序
- Python基础9--排序
- 9中排序算法
- 9 -- 鸡尾酒排序
- DataStructure-9-排序技术
- 年龄排序9
- javascript数据结构9-排序
- 9BASC代码排序
- header如何设置为图片
- JAVA学习笔记07——Hibernate框架第一章
- 实例分析Class字节码文件(三)
- MySql存储过程语法及事例
- 想要写出高性能sql语句,你得记住这些
- 排序 9
- _OBJC_CLASS_$_某文件名", referenced from:的问题
- form提交的错觉
- Java动态代理
- mysql用户与权限
- Unity 滑动事件6个方向的实现
- HDU
- CentOS7学习(1)
- [POJ2151]check the difficulty-概率DP