1、队列和栈
在数据结构中,队列和栈是我们再熟悉不过的两种结构了叭,简单来说,栈就是“先进后出”的结构,队列就是“先进先出”的结构。下面我们来具体实现它吧~
1.1队列的实现
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<conio.h>
using namespace std;
typedef struct student
{
int data;
struct student* next;
}node;
typedef struct QueueLink
{
node* front;
node* rear;
}queue;
//队列的入队
queue *insert(queue *HQ, int x)
{
node* s;
s = (node*)malloc(sizeof(node));
s->data = x;
s->next = NULL;
if(HQ->rear == NULL)
{
HQ->front = s;
HQ->rear = s;
}
else
{
HQ->rear->next = s;
HQ->rear = s;
}
return HQ;
}
//队列的出队
queue *del(queue *HQ)
{
node* p;
int x;
if(HQ->first == NULL)
{
printf("yichu");
}
else
{
x = HQ->first->data;
p = HQ->first;
if(HQ->front == HQ->rear)
{
HQ->front = NULL;
HQ->rear = NULL;
}
else
{
HQ->front = HQ->front->next;
free(p);
}
return HQ;
}
}
1.2栈的实现
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<conio.h>
using namespace std;
typedef struct student
{
int data;
struct student* next;
}node;
typedef struct StackLink
{
node* zhandi;
node* top;
}stack;
//入栈
stack* push(stack *HQ,int x)
{
node* s;
s = (node*)malloc(sizeof(node));
s->data = x;
s->next = NULL;
if(HQ->zhandi == NULL)
{
HQ->zhandi = s;
HQ->top = s;
}
else
{
HQ->top->next = s;
HQ->top = s;
}
return HQ;
}
//出栈
queue *pop(queue *HQ)
{
node* p;
int x;
if(HQ->zhandi == NULL)
{
printf("yichu\n");
}
else
{
p = HQ->zhandi;
x = HQ->zhandi->data;
if(HQ->zhandi == HQ->top)
{
HQ->zhandi = NULL;
HQ->top = NULL;
}
else
{
while(p->next != HQ->top)
{
p = p->next;
}
HQ->top = p;
HQ->top->next = NULL;
}
return HQ;
}
}
1.3用一个队列来实现栈结构
实质上就是使用先进先出的原则实现先进后出的结构,所以,C++实现,用一个队列即可实现,只用将n-1队尾元素拿出来头插,再出队尾元素,或是删除队尾元素,即可实现一个栈先进后出的功能
代码实现:
class MyStack {
public:
/** Initialize your data structure here. */
MyStack() {
}
/** Push element x onto stack. */
void push(int x) {
q1.push(x);
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
int size = q1.size() - 1;
for(size_t i = 0; i < size ;++i)
{
q1.push(q1.front());
//把队列前面的元素全部拿出来重新入队
q1.pop();
}
//此时栈顶元素就是队列的队头元素
int front = q1.front();
//出队
q1.pop();
return front;
}
/** Get the top element. */
int top() {
return q1.back();
}
/** Returns whether the stack is empty. */
bool empty() {
if(q1.empty())
return true;
else
return false;
}
private:
queue<int> q1;
};
1.4用一个栈实现队列结构
实质上是使用先进后出的性质实现先进先出的结构。 所以,用c++实现,一个栈就可以。只用将栈顶n-1个元素拿出来入队,然后返回栈底的值,再把队列里面的元素出队入栈。重复上述操作即可。
代码实现:
class MyQueue {
public:
stack<int> s;
stack<int> h;
/** Initialize your data structure here. */
MyQueue() {
}
/** Push element x to the back of queue. */
void push(int x) {
s.push(x);
}
/** Removes the element from in front of queue and returns that element. */
int pop() {
while(s.size() != 1)
{
h.push(s.top());
s.pop();
}
int ans = s.top();
s.pop();
while(!h.empty())
{
s.push(h.top());
h.pop();
}
return ans;
}
/** Get the front element. */
int peek() {
while(s.size() != 1)
{
h.push(s.top());
s.pop();
}
int ans = s.top();
while(!h.empty())
{
s.push(h.top());
h.pop();
}
return ans;
}
/** Returns whether the queue is empty. */
bool empty() {
return s.empty();
}
};
1.5用两个栈实现队列的功能
#include<stack>
#include<iostream>
uisng namespace tsd;
tempalte<class T>
struct MyQueue
{
void push(T &t)
{
s1.push(t);
}
T front()
{
if(s2.empty())
{
if(s1.size() == 0) throw;
while(!s2.empty())
{
s2.push(s1.top());
s1.pop();
}
}
return s2.top();
}
void pop()
{
if(s2.empty())
{
while(!s1.empty())
{
s2.push(s1.top());
s1.pop();
}
}
if(! s2.empty())
s2.pop();
}
stack<int> s1;
stack<int> s2;
};
2、堆和栈的区别
首先我们来了解一下内存一般分为哪几个类别
- 栈区:由编译器自动分配和释放。存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈
- 堆区:一般由程序员分配和释放,若程序员不释放,程序结束时可能由操作系统回收。注意,这个数据结构中的堆不是一回事儿,这更类似于链表
- 全局区(静态区):全局变量和静态变量存放在一起的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态比阿娘在相邻的另一块区域。程序结束后由系统释放
- 文字常量区:常量字符串就放在这里,程序结束后由系统释放
- 程序代码区区:存放函数体的二进制代码
具体的解释请参考另外一篇博文进程的虚拟地址空间
接下来,我们就来详细的介绍他们之间的区别吧~
1、申请方式
栈是由系统自动分配,但是堆是程序员自己申请的。例如:p1=(char*)mallco(10);和int *p2 = new int(10).注意!!!p1和p2本身是在栈中的。
2、申请后系统的响应
只要栈的剩余空间大于所申请的空间,系统将为程序提供内存,否则报错。而对于堆来说,我们知道操作系统有一个记录空闲内存地址的链表,堆的调用就去链表中寻找符合自己申请空间的节点,这块内存空间中的首地址记录本次分配的大小。
3、申请大小的限制
在windows下,栈的大小是2MB。而堆获取的空间比较灵活,也比较大
4、申请效率的比较
因为栈是程序自动分配,所以速度比较快但是程序员无法控制。但是new一般速度比较慢,而且容易产生碎片,但是用起来很方便。
5、栈和堆的存储内容
栈:在函数调用的时候。第一个进栈的是主函数中的下一条指令的地址,然后是函数的各个参数,然后是参数从右向左入栈,然后是局部变量。注意!!!静态变量是不入栈的。
堆:一般是在堆的头部用一个字节存放堆的大小,堆中的内容由程序员自行安排
6、存取效率的比较
栈中的数据是在运行的时候赋值的,但是堆中的数据是在编译时就确定的。栈比堆快。