惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

罗磊的独立博客
G
Google Developers Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
腾讯CDC
有赞技术团队
有赞技术团队
Vercel News
Vercel News
MongoDB | Blog
MongoDB | Blog
M
MIT News - Artificial intelligence
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
B
Blog RSS Feed
I
InfoQ
Blog — PlanetScale
Blog — PlanetScale
博客园_首页
The Cloudflare Blog
B
Blog
C
Check Point Blog
Stack Overflow Blog
Stack Overflow Blog
IT之家
IT之家
U
Unit 42
D
Docker
月光博客
月光博客
aimingoo的专栏
aimingoo的专栏
博客园 - Franky
A
About on SuperTechFans

Posts on WKLKEN THINKING

apisix 中的 lrucache apisix 中的服务发现机制 apisix 中的负载均衡 apisix etcd机制 聊聊框架 关于 k8s 的 zero downtime deployment 一些建议 apisix 遇到的一些问题 关于在除夕前一天换了一个洗衣机的故事 Django DRF 性能优化 DRF 的一些实践 Part1: Serializer DRF继承关系图 Better Code: 关于接口的灵活性 新的仓库: wklken/naming 缓存使用的一些经验 Better Code: 抽象: 可扩展性与可维护性的抉择 Better Code: 异常时, 该提示用户哪些信息? Better Code: 更好的异常日志打印 Go: some libs Go: go-redis/cache升级的坑 Go: logrus性能提升 Go: gin validation 远程办公的一点总结 Go: 开发过程中的一些bug 项目管理实践: 风险驱动开发 Go: 一种error wrap调用链处理方式 漫谈技术选型 Go: 基于 apitest 做handler层单元测试 Go: go-sql-driver interpolateparams参数优化 [分享]深度工作 你需要更多的思考时间
数据结构&算法实践—【排序|选择排序】堆排序
2012-06-02 · via Posts on WKLKEN THINKING

排序»选择排序»堆排序

List:

0.概念+伪代码+示例分析
1.堆排序实现
2.Question
  1. start

基本概念:

维基百科http://zh.wikipedia.org/zh-cn/%E5%A0%86%E7%A9%8D%E6%8E%92%E5%BA%8F

function heapSort(A : list[1..n]) {
    max_heap = make_max_heap(A)  #构建一个最大堆
    i = 1
    while(max_heap.size() > 0){   #当堆中还存在值
        A[n-i] = max_heap.pop_max()   #取出最大一个
        i++
    }
}

堆为一棵完全二叉树,每个节点值都>=子节点值

堆排序根据这个特性,首先将所有元素建立堆,然后一个个取出,即有序的

堆中每个节点的位置:

父节点i的左子节点在位置 (2*i);
父节点i的右子节点在位置 (2*i+1);
子节点i的父节点在位置 floor(i/2);

最大堆主要操作逻辑:

插入:将新元素加入完全二叉树最后一个节点,依次往上,调整直到满足父节点值都>=子节点值

删除:移除根节点,将最后一个节点拿到根节点,依次往下,调整

原始:

heap1

插入操作:12,先假定放在最后一个位置,然后从这个节点开始往上,同父节点比较,依次调整

heap2

删除:取走11,将最后一个元素8移到根节点,从上往下,重新调整

heap3

  1. start

根据公式,我们可以使用数组模拟实现完全二叉树(不使用首个位置)

首先,我们先实现堆:

#!/usr/bin/python
# -*- coding:utf-8 -*-
#堆排序
#@author: wklken@yeah.net

#先实现一个最大堆
class MaxHeap:
    def __init__(self):
        self.heap = [0]  #第一个元素用不到,只是为了将下标转为1开始,方便计算节点的位置
    def isEmpty(self):
        return len(self.heap) == 1
    def size(self):
        return len(self.heap) - 1
    #插入节点
    def insert(self, value):
        i = len(self.heap)
        self.heap.append(value)
        while i != 1 and value > self.heap[i/2]:  #如果插入节点大于其父节点,需要交换二者,反复,直到值小于父节点
            self.heap[i], self.heap[i/2] = self.heap[i/2], self.heap[i]  #父节点下移
            i = i/2
        self.heap[i] = value  #把 value插入对应位置
    #删除最大节点——最大的是根节点
    def deleteMax(self):
        if self.isEmpty(): #没有元素了
            return None
        x = self.heap[1]  #最大

        last = self.heap.pop()
        if self.size() == 0: #每次取最后一个,若是只剩两个的情况,pop
            return x
        #每次,移除根节点,将树的最后一个节点挪到根节点,然后从上到下,调整位置,保证树是一个最大堆
        i = 1
        ci = 2
        current_size = self.size()
        while  ci <= current_size:
            if ci < current_size and self.heap[ci] < self.heap[ci+1]:
                ci += 1

            if last >= self.heap[ci]:
                break

            self.heap[i] = self.heap[ci]
            i = ci
            ci *= 2
        self.heap[i] = last
        return x

    def initFromList(self, l):
        self.heap.extend(l)
        size = self.size()
        #从最后一棵子树开始,调整每一棵子树
        for i in range(size/2,0,-1):
              t_root = self.heap[i]

              c = 2*i
              while c <= size:
                  if c < size and self.heap[c] < self.heap[c+1]:
                      c += 1
                  if t_root >= self.heap[c]:
                      break
                  self.heap[c/2] = self.heap[c]
                  c *= 2
                  self.heap[c/2] = t_root

然后,实现排序过程:

:::python
def heap_sort(l):
    m = MaxHeap()
    m.initFromList(l)
    result = []
    for i in range(len(l)):
        result.append(m.deleteMax())
        print result
    return result
  1. start

A.概念,过程描述?

B. 时间复杂度?空间复杂度?是否是稳定排序?

C.适用场景,何种情况下表现最优