栈和队列

在对顺序表和链表有了一定的了解之后,我们来讨论两种更为具体的模型——栈和队列。

栈的基本描述

栈(stack)是一种限定只在尾部插入和删除的模型结构,根据栈的这个特点我们把栈的修改原则称为先进后出,后进先出原则,我们把栈的头部称为栈底,栈的尾部称为栈顶,也就是说栈的一系列操作都是在栈顶完成的。

栈的图解

在这里插入图片描述

栈的基本操作

相对于顺序表和链表来说栈的操作就要简单许多,因为栈的一系列操作仅仅在栈顶完成。
只在尾部操作的话,我们一般选用顺序表来实现栈的编写。

栈的初始化

void StackInit(Stack *s){
	s->top = 0;
}

压栈(实际是尾插)

void StackPush(Stack*s, char v){
	s->array[s->top++] = v;
}

出栈(实际是尾删)

void StackPop(Stack*s){
	s->top--;
}

查看栈顶元素

int StackTop(Stack*s){
	return s->array[s->top - 1];
}

查看元素个数

int StackSize(Stack *s){
	return s->top;
}

判断栈是否为空

bool StackEmpty(Stack *s){
	return s->top == 0;//栈为空返回 true
}

队列

队列的基本描述

队列(queue)顾名思义,就像我们日常生活中的排队一样,从队尾走到队首,最先进队伍的人最先出队伍,队列的修改原则是先进先出

队列的图解

在这里插入图片描述

队列的基本操作

队列限定只在尾部插入和头部删除,在队首和队尾操作,这样的操作用链表实现更为方便。

队列的初始化

void QueueInit(Queue *q){
	q->head = q->last = NULL;
}

队列的进入(尾插)

void QueuePush(Queue *q, int v){
	Node *node = (Node*)malloc(sizeof(Node));
	node->value = v;
	node->next = NULL;
	if (q->head == NULL){
		q->head = node;
	}
	else{
		q->last->next = node;
		q->last = node;
	}
}

队列的出队(头删)

void QueuePop(Queue*q){
	Node*second = q->head->next;
	free(q->head);
	q->head = second;
	if (q->head == NULL){
		q->last == NULL;
	}
}

返回队首元素

int QueueFront(Queue*q){
	return q->head->value;
}

队列大小

int QueueSize(Queue *q){
	int size = 0;
	for (Node*n = q->head; n != NULL; n = n->next){
		size++;
	}
	return size;
}

判断队列是否为空

bool QueueEmpty(Queue *q){
	return q->head == NULL;
}

了解了栈和队列的这些基本操作,接下来我们看看栈和队列的相互实现。

用队列实现栈

队列的特点是先进先出,而栈的特点是先进后出,这就要将一个队列中每次队首的元素移动到队尾,出最后一个进队列的元素。
在这里插入图片描述
具体实现:

class MyStack {
public:
    queue<int> q;
    /** Initialize your data structure here. */
    MyStack() {
        
    }
    
    /** Push element x onto stack. */
    void push(int x) {
        //压栈没有特殊性
        q.push(x);
    }
    
    /** Removes the element on top of the stack and returns that element. */
    int pop() {
        //出栈首先得挪动size-1个数
        int size = q.size();
        for(int i = 0;i<size-1;i++){
            //拿出队首元素
            int v = q.front();
            //删除
            q.pop();
            //再从后进入队列
            q.push(v);
        }
        int v = q.front();
        q.pop();
        return v;
    }
	
	/** Get the top element. */
    int top() {
        //出栈首先得挪动size-1个数
        int size = q.size();
        for(int i = 0;i<size-1;i++){
            //拿出队首元素
            int v = q.front();
            //删除
            q.pop();
            //再从后进入队列
            q.push(v);
        }
        int v = q.front();
        q.pop();
        q.push(v);

        return v;
    }
    
    /** Returns whether the stack is empty. */
    bool empty() {
        //队列为空 栈就为空
        return q.empty();
    }
};

用栈实现队列

队列的特点是先进先出,而栈的特点是先进后出,所以用栈实现队列,我们应该在内部选取两个栈来完成队列的实现。
在这里插入图片描述
具体实现:

class MyQueue {
public:
    stack<int> in;
    stack<int> out;
    /** Initialize your data structure here. */
    MyQueue() {
        
    }
    
    /** Push element x to the back of queue. */
    void push(int x) {
        in.push(x);
    }
    
    /** Removes the element from in front of queue and returns that element. */
    int pop() {
        //如果out为空,把所有in的数据导入到out
        if(out.empty()){
            while (!in.empty()){
                int v = in.top();
                in.pop();
                out.push(v);
            }
        }
        int v = out.top();
        out.pop();
        return v;
    }
    
    /** Get the front element. */
    int peek() {
        //如果out为空,把所有in的数据导入到out
        if(out.empty()){
            while (!in.empty()){
                int v = in.top();
                in.pop();
                out.push(v);
            }
        }
        int v = out.top();
        return v;
    }
    
    /** Returns whether the queue is empty. */
    bool empty() {
        return in.empty() && out.empty();
    }
};

最小栈

最小栈即每次出栈元素都是这个栈中的最小值,首先正常出栈是没法实现的(即图中的正常栈),我们必须再找一个栈用来存放每次压栈完成的最小值(即图中的最小栈),用x(压入正常栈的元素)和最小栈栈顶元素比较,如果小于最小栈栈顶元素,则将x压入最小栈,否则将最小栈栈顶元素压入最小栈。

在这里插入图片描述
具体实现:

class MinStack {
public:
    stack<int> normal;
    stack<int> min;
    /** initialize your data structure here. */
    MinStack() {
        
    }
    
    void push(int x) {
        normal.push(x);
        if(min.empty()||x<=min.top()){
            min.push(x);
        }
        else{
            min.push(min.top());
        }
    }
    
    void pop() {
        normal.pop();
        min.pop();
    }
    
    int top() {
        return normal.top();
    }
    
    int getMin() {
        return min.top();
    }
};

循环队列

循环队列即类似于环形的队列
在这里插入图片描述
具体实现:

class MyCircularQueue {
public:
    int *array;//保存空间指针
    int capacity;//容量
    int size;//实际数据个数
    int front;//当前队首数据下标
    int vear;//当前队尾可用位置下标
    /** Initialize your data structure here. Set the size of the queue to be k. */
    MyCircularQueue(int k) {
        array = (int*)malloc(sizeof(int)*k);
        capacity = k;
        size = 0;
        front = 0;
        vear = 0;
    }
    
    /** Insert an element into the circular queue. Return true if the operation is successful. */
    bool enQueue(int value) {
        if(size == capacity){
            return false;
        }
        else{
            array[vear] = value;
            vear = (vear+1)%capacity;
            size++;
            return true;
        }
    }
    
    /** Delete an element from the circular queue. Return true if the operation is successful. */
    bool deQueue() {
        if(size == 0){
            return false;
        }
        else{
            front = (front+1)%capacity;
            size--;
            return true;
        }
    }
    
    /** Get the front item from the queue. */
    int Front() {
        if(size == 0){
            return -1;
        }
        else{
            return array[front];
        }
    }
    
    /** Get the last item from the queue. */
    int Rear() {
        if(size == 0){
            return -1;
        }
        else{
            int index = (vear-1+capacity)%capacity;
            return array[index];
        }
    }
    
    /** Checks whether the circular queue is empty or not. */
    bool isEmpty() {
        return size == 0;
    }
    
    /** Checks whether the circular queue is full or not. */
    bool isFull() {
        return size == capacity;
    }
};

栈的应用(深度优先):1.括号匹配 2.迷宫的暴力破解 3.函数调用栈 4.逆波兰表达式
队列的应用(广度优先):1.操作系统的调用 2.消息队列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值