堆排序
堆排序的基本思想:
对于一组待排序数据,首先按堆的定义建立初始堆(大根堆或小根堆);
取出堆顶元素(最大或最小),将剩余的元素继续调整成新堆,就得到次大或次小元素;
反复执行 1、2 ,直到全部元素排序成顺序或逆序,堆排序结束
#include<stdio.h>
// 交换
void swap(int arr[], int i, int j) {
int temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
// 调整堆结构
void heapify(int tree[], int n, int i) {
for (int j = 2 * i + 1; j < n; j = j * 2 + 1) {
int parent = (j - 1) / 2;
if (j + 1 < n && tree[j] < tree[j + 1]) {
j++;
}
if (tree[parent] < tree[j]) {
swap(tree, parent, j);
}
else { break; }
}
}
//构造堆,二叉树中最后一个非叶子结点为n/2-1,就从最后一个非叶子结点倒序调整堆结构就彳亍了
void build_heap(int tree[], int n) {
for (int i = n / 2 - 1; i >= 0; i--) {
heapify(tree, n, i);
}
}
//排序
void heapSort(int tree[], int n) {
biuld_heap(tree, n);
for (int i = n - 1; i >= 0; i--) {
swap(tree, i, 0);
heapify(tree, i, 0);
}
}
int main()
{
int tree[] = { 0, 45, 56, 65, 81, 90, 59, 52, 51, 10, 23, 15, 40, 61, 72, 66, 21, 76, 58, 94 };
int size = 20;
heapSort(tree, size);
for (int ind = 0; ind < size; ind++) {
printf("%d\n", tree[ind]);
}
return 0;
}
调整堆结构中,自上向下调整
因为如果结点的左右孩子中有比当前结点大的,那么找到左右孩子的最大值,然后交换两个结点,未交换的孩子结点不用考虑,因为已经是堆结构了,它的左右孩子肯定小于或者大于它本身。
然后我们再把当前结点设置为已经交换了孩子结点,因为虽然孩子结点已经符合堆结构但是可能交换数值之后就构不成堆结构。
构造堆的时候,自下向上构造
因为调整堆结构的函数中输入结点的左右孩子必须符合堆结构,所以说只能从下到上来逐步构造。
排序
排序的时候是交换最后一个结点和根节点的数值然后,重新再调整堆结构。
class Heap(object):
def __init__(self, heap):
self.heap = heap
self.size = len(self.heap)
def __str__(self): # 为了方便查看
return str(self.heap)
def _heapify(self, target, n):
i = 2*target + 1
rec = target
while i < n:
if i + 1 < n and self.heap[i] < self.heap[i+1]:
i += 1
if self.heap[rec] < self.heap[i]:
self.heap[rec], self.heap[i] = self.heap[i], self.heap[rec]
else: break
i,rec = 2*i + 1, i
def build_heap(self):
for i in range(self.size//2-1, -1, -1):
self._heapify(i, self.size)
def heap_sort(self):
self.build_heap()
for i in range(self.size-1, -1, -1):
self.heap[i], self.heap[0] = self.heap[0], self.heap[i]
self._heapify(0, i)
def _shiftUp(self, ind):
while (ind-1) // 2 >= 0 and self.heap[(ind-1)//2] < self.heap[ind]:
self.heap[ind], self.heap[(ind-1)//2] = self.heap[(ind-1)//2], self.heap[ind]
ind = (ind-1)//2
def add(self, val):
self.heap.append(val)
self._shiftUp(self.size)
self.size += 1
def Pop(self):
self.heap[0] = self.heap[-1]
self.size -= 1
self.heap.pop()
self._heapify(0, self.size)
def peek(self):
return self.heap[0]
if __name__ =='__main__':
arr = [4, 8, 3, 9, 10, 2]
heap_arr = Heap(arr)
heap_arr.build_heap()
heap_arr.add(20)
print(heap_arr)
heap_arr.Pop()
print(heap_arr)