资深守护
push模板
void push(int e){
int i=++pq.size;
while (i/2){
if (e>=pq.a[i/2]) break;
pq.a[i]=pq.a[i/2];
i=i/2;
}
pq.a[i]=e;
}
pop模板
int pop(){
int res=pq.a[1];
int e=pq.a[pq.size];
pq.size--;
int i=1;
while(i*2<=pq.size){
int minval=2*i;
if (2*i+1<=pq.size){
if (pq.a[minval]>pq.a[2*i+1]){
minval=2*i+1;
}
}
if (pq.a[minval]>=e) break;
pq.a[i]=pq.a[minval];
i=minval;
}
pq.a[i]=e;
return res;
}
定义
struct PQ{
int a[10010];
int size;
};
PQ pq;
中级守护
以前学过,希望能帮到你
#include<iostream>
#include<stack>
using namespace std;
int main()
{
stack<int> first;
first.push(3);
cout<<"Top data:"<<first.top()<<endl;
cout<<"Size of first:"<<first.size()<<endl;
return 0;
}
中级天翼
堆的push,pop数组实现
堆是形如下图的二叉树
堆的最重要的性质,就是儿子的值一定不小于父亲的值。树的节点从上到下,从左到右的顺序紧凑排列。
【插入数据】push
首先在堆的末尾插入数据,然后不断向上提升直到没有大小颠倒
【删除数据】pop
从堆中删除最小的数据
先将堆中最后一个节点的值复制到根节点上,并且删除最后一个节点。然后不断向下交换,直到没有大小颠倒;
在向下交换的过程中,如果有两个儿子,则与其中较小的交换(如果儿子比自己小)。
【堆的操作复杂度】
两种操作都与树的深度成正比。 因此,如果有n个元素,那么每个操作的复杂度为O(logn);
【堆的实现】
给每个元素按照从上到下从左到右的顺序编号,并用数组来储存,此时儿子的编号满足如下性质
1.左儿子的编号是自己编号 x 2 + 1;
2.右儿子的编号是自己编号 x 2 + 2;
#include <iostream>
using namespace std;
const int maxn=10000;
class priority_q{
public:
priority_q(){
sz = 0; //size 初始化为0;
}
void push(int x);
int pop();
int size(){
return this->sz;
}
private:
int heap[maxn],sz;
};
void priority_q::push(int x){
int i = sz++;
while(i > 0){
// 父亲节点的编号
int p = (i - 1)/2;
if(heap[p] <= x) break;
//把父亲的节点放下来
heap[i] = heap[p];
//当前节点更新
i = p;
}
heap[i] = x;
}
int priority_q::pop(){
int ret = heap[0]; //根,最小值
int x = heap[--sz]; //最后一个节点, 放到根的数值
int i = 0;
//从根向下交换
while(i * 2 + 1< sz){
int a= i * 2 + 1, b= i * 2 + 2; //两个儿子的位置
if(b < sz && heap[b]< heap[a]) a = b; //选出 最小的儿子
if(heap[a] >= x) break; //如果没有大小颠倒 退出
//把儿子的值提上来
heap[i] = heap[a];
i = a;
}
heap[i] = x; //最终在找到的位置 i 填入 x;
return ret;
}
int main(){
priority_q pq;
pq.push(5);
pq.push(10);
pq.push(7);
pq.push(2);
int size = pq.size();
for(int i = 0; i < size; i++){
cout<<"第"<<i+1<<"个数"<<pq.pop()<<endl;
}
return 0;
}
中级天翼
堆栈是存储器中专用的缓冲区,用于暂存寄存器数据或地址指针,push/pop就用于堆栈的操作,这两个指令一般用在:
1、子程序调用,为了保护现场,把所要用的寄存器中的内容先暂时保存起来,在子程序调用结束之前,按照先进后出的原则,把数据恢复。
2、有时候,需要临时用一下某些寄存器,也可用一下,凭个人喜好;
这两个指令必须成对使用(特殊用途除外),你只要压入了那些东西,并且知道他们的顺序就行了,所操作的是字符还是数据,就不用知道了。
堆栈操作指令
堆栈是一个先进后出的主存区域,位于堆栈段中,使用SS段寄存器记录器段地址。栈只有一个出口,即当前栈顶。栈顶是地址较小的一端(低端),它用堆栈指针寄存器SP指定。堆栈的两种基本操作,对应两条基本指令:
(1)、进栈指令push
push reg/mem/seg;sp<-sp-2,ss<-reg/mem/seg
进栈指令先使堆栈指令sp减2,然后把一个字操作数存入堆栈顶部。堆栈操作的对象只能是字操作数,进栈时底字节存放于低地址,高字节存放于高地址,sp相应向低地址移动两个字节单元。
push AX
PUSH [2000H]
PUSH CS
(2)、出栈指令pop
pop reg/seg/mem;reg/seg/mem<-ss:[sp],sp<-sp+2
出栈指令把栈顶的一个字传送至指定的目的操作数,然后堆栈指针sp加2。目的操作数应为字操作数,字从栈顶弹出时,低地址字节送低字节,高地址字节送高字节。
pop AX
POP [2000H]
POP SS堆栈可以用来临时存放数据,以便随时恢复它们。也常用于子程序见传递参数。
注意几点:
(1)、因为堆栈指针sp总是指向已经存入数据的栈顶(不是空单元),所以PUSH指令是将(SP)减2,后将内容压栈(即先修改SP是指指向空单元,后压入数据),而POP是先从栈顶弹出一个字,后将堆栈指针SP加2.
(2)、PUSH CS是合法的,但是POP CS是不合法的。
(3)、因为SP总是指向栈顶,而用PUSH和POP指令存取数时都是在栈顶进行的,所以堆栈是先进后出或叫后进先出的。栈底在高地址,堆栈是从高地址向低地址延伸的,所有栈底就是最初的栈顶。
(4)、用PUSH指令和POP指令时只能按字访问堆栈,不能按字节访问堆栈。
(5)、PUSH和POP指令都不影响标志。
新手光能
我不需要酷町豆,大发慈悲一下!!!!
struct Heap {
int a[10000];
int size;
};
Heap heap;
void push(Heap &pq, int e) {
int i=++pq.size;
while (i/2) {
if (e>=pq.a[i/2]) break;
pq.a[i]=pq.a[i/2];
i=i/2;
}
pq.a[i]=e;
}
int pop(Heap &pq) {
int res=pq.a[1];
int e=pq.a[pq.size];
pq.size--;
int i=1;
while (i*2<=pq.size) {
int minval=2*i;
if (2*i+1<=pq.size) {
if (pq.a[minval]>pq.a[2*i+1]) minval=2*i+1;
}
if (pq.a[minval]>=e) break;
pq.a[i]=pq.a[minval];
i=minval;
}
pq.a[i]=e;
return res;
}