堆
问题:程序的输入包含两个整数m和n,其中m<n。输出是0~n-1范围内m个随机整数的有序列表
堆是用来表示元素集合的一种数据结构。
“/”向下取整
Shitup(n)函数:将n加入堆底,并排序
Shitdown(n)函数:将n加入堆顶,并排序
优先级队列:
Insert函数在集合中插入一个新元素
Extractmin:删除集合中最小的元素
优先级队列排序:
template<typename T>
class PriQueue{
private:
int n, maxsize;
T *x;
void swap(int i, int j)
{
T temp = x[i];
x[i] = x[j];
x[j] = temp;
}
public:
PriQueue(int m) :maxsize(m)
{
x = new T[maxsize + 1];
n = 0;
}
void insert(T t)
{
int i, p;
x[++n] = t;
//自底向上类似siftup函数内容实现优先级序列
for (i = n ; i > 1 && x[p=i/2] > x[i] ; i = p)
swap(p, i);
}
//输出队列顶并调整队列结构
T extramin()
{
/*cout << "队列中的数据为:" << endl;
for (int i = 1; i <= n; i++)
cout << x[i] << "\t";
cout << endl;*/
int i, c;
T t = x[1];
x[1] = x[n--];
//自顶向下调整队列结构
for (i = 1; (c = 2 * i) <= n; i = c)
{
if (c + 1 <= n && x[c + 1] < x[c])
c++;
if (x[i] <= x[c])
break;
swap(c, i);
}
return t;
}
};
调用:
/************************************************************************/
/* 解决问题的向量排序算法 */
/************************************************************************/
template<typename T>
void pqsort(T *v , int n)
{
PriQueue<T> pq(n);
for (int i = 0; i < n; i++)
{
pq.insert(v[i]);
}
for (int j = 0; j < n; j++)
{
v[j] = pq.extramin();
}
}
const int N = 10;
int main()
{
int arr[N] = { 4, 12 , 56 , 32 , 24 , 68 , 33 , 6 , 7 , 2 };
cout << "排序前输入数据为 :"<<endl;
for (int j = 0; j < N; j++)
{
cout << arr[j] << "\t";
}
cout << endl;
pqsort(arr,N);
cout << "排序后输出数据为 : " << endl;
for (int j = 0; j < N; j++)
{
cout << arr[j] << "\t";
}
cout << endl;
system("pause");
return 0;
}
n次insert和extractmin操作在最坏情况下的开销是O(nlogn),优于快速排序算法的最坏O(n^2)的复杂度,但是缺点是,该算法需要额外的n+1的字节的空间来存储数组x[0…n];
堆排序算法:
对于优先级队列实现的向量排序算法,需要两个数组,一个用于优先级队列,一个用于待排序的元素;而堆排序算法只需要一个数组,因此节省了空间开销。
思想:使用单个数组x同时表示两种抽象结构,左边是堆,右边是输入元素序列。元素的初始顺序是随意的,而最终则是有序的。