堆排序
来源:互联网 发布:淘宝千色药妆是正品么 编辑:程序博客网 时间:2024/05/17 03:09
一些概念
普通队列:先进先出,后进先出(顺序已经确定)
优先队列:出队顺序与入队顺序无关,和优先级相关(动态确定顺序)
优先队列在处理动态问题上很有优势,同时处理静态问题也是比较好的,比如在100000000个元素中选出前100名?也就是,在N个元素中选出前M个元素。不同方法的时间复杂度分别是排序:
动态
有新的元素会加入数据结构,同时又有元素会离开队列,也就是说入队和出队是有限队列的两个基本特征。
出队:取出优先级最高的元素。
堆的存储
1)节点值总是不大于父亲节点的值;
2)完全二叉树。
由于堆是一颗完全二叉树,所以可以用数组来存储一颗二叉树。
ShiftUp
入队时,从末端加入元素,然后要调整元素顺序,使其任然维持最大堆的定义,关键操作是每次和父亲相比较,逐层向上升直到满足堆的定义。
void shiftUp(int k){ while (k > 1 && data[k / 2] < data[k]){ swap(data[k / 2], data[k]); k /= 2; }}
ShiftDown
出队只能取出根节点的元素,出队后为了保证完全二叉树,可以将最后一个元素与根节点位置交换,然后对根节点元素进行ShiftDown操作。
void shiftDown(int k){ while (2 * k <= count){ int j = 2 * k; // 在此轮循环中,data[k]和data[j]交换位置 if (j + 1 <= count && data[j + 1] > data[j]) j++; // data[j] 是 data[2*k]和data[2*k+1]中的最大值 if (data[k] >= data[j]) break; swap(data[k], data[j]); k = j; }}
堆的数据结构
template<typename Item>class MaxHeap{private: Item *data; int count; int capacity; void shiftUp(int k){ while (k > 1 && data[k / 2] < data[k]){ swap(data[k / 2], data[k]); k /= 2; } } void shiftDown(int k){ while (2 * k <= count){ int j = 2 * k; // 在此轮循环中,data[k]和data[j]交换位置 if (j + 1 <= count && data[j + 1] > data[j]) j++; // data[j] 是 data[2*k]和data[2*k+1]中的最大值 if (data[k] >= data[j]) break; swap(data[k], data[j]); k = j; } }public: MaxHeap(int capacity){ data = new Item[capacity + 1]; count = 0; this->capacity = capacity; } ~MaxHeap(){ delete[] data; } int size(){ return count; } bool isEmpty(){ return count == 0; } void insert(Item item){ assert(count + 1 <= capacity); data[count + 1] = item; shiftUp(count + 1); count++; } Item extractMax(){ assert(count > 0); Item ret = data[1]; swap(data[1], data[count]); count--; shiftDown(1); return ret; } Item getMax(){ assert(count > 0); return data[1]; }};
Heapify
MaxHeap(Item arr[], int n){ data = new Item[n + 1]; capacity = n; for (int i = 0; i < n; i++) data[i + 1] = arr[i]; count = n; for (int i = count / 2; i >= 1; i--) shiftDown(i);}
堆排序
template<typename T>void heapSort2(T arr[], int n){ MaxHeap<T> maxheap = MaxHeap<T>(arr,n); for( int i = n-1 ; i >= 0 ; i-- ) arr[i] = maxheap.extractMax();}template<typename T>void heapSort1(T arr[], int n){ MaxHeap<T> maxheap = MaxHeap<T>(n); for( int i = 0 ; i < n ; i ++ ) maxheap.insert(arr[i]); for( int i = n-1 ; i >= 0 ; i-- ) arr[i] = maxheap.extractMax();}
使用Heapify构建堆,时间复杂度是
堆排序优化
原地堆排序,空间复杂度是
template<typename T>void __shiftDown(T arr[], int n, int k){ while( 2*k+1 < n ){ int j = 2*k+1; if( j+1 < n && arr[j+1] > arr[j] ) j += 1; if( arr[k] >= arr[j] )break; swap( arr[k] , arr[j] ); k = j; }}template<typename T>void __shiftDown2(T arr[], int n, int k){ T e = arr[k]; while( 2*k+1 < n ){ int j = 2*k+1; if( j+1 < n && arr[j+1] > arr[j] ) j += 1; if( e >= arr[j] ) break; arr[k] = arr[j]; k = j; } arr[k] = e;}template<typename T>void heapSort(T arr[], int n){ // 首先进行Heapify操作 for( int i = (n-1)/2 ; i >= 0 ; i -- ) __shiftDown2(arr, n, i); // 然后每次把堆顶元素与最后一个叶子交换,之后堆堆顶元素进行shiftDown操作 for( int i = n-1; i > 0 ; i-- ){ swap( arr[0] , arr[i] ); __shiftDown2(arr, i, 0); }}
阅读全文
0 0
- 堆及堆排序
- 堆/堆排序特点
- 【二叉堆、堆排序】
- 二叉堆 & 堆排序
- 二叉堆 & 堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆和堆排序
- 堆排序(最大堆)
- 堆和堆排序
- 堆和堆排序
- 堆及堆排序
- 堆和堆排序
- 堆与堆排序
- Docker下搭建DNS服务器
- Algorithm学习笔记 --- C语言实现二分查找
- 折半插入排序
- RainMeter,一款创意桌面软件
- Python os模块介绍
- 堆排序
- 1011:"水仙花数”问题2
- pip离线环境安装
- h3c交换机combo口的应用
- AUC ROC
- 防火墙配置
- 系统相关功能开发(二)-磁盘操作
- 最大熵模型总结
- CodeForces