队列实现: (单链表)
队列: 先进先出原则
入队: 尾插
出队: 头删
实现: 顺序表,链表
顺序表: 尾插O(1) 头删O(n)
单链表: 尾插O(n) 头删O(1)
含有尾指针的单链表,尾插O(1) 头删O(1)
常用实现方式: 含有尾指针的单链表,尾插O(1) 头删O(1)
顺序表,链表
栈, 队列: 元素的访问操作和顺序有一定的规则
声明文件
#pragma once
#include <stdlib.h>
#include <stdio.h>
typedef int QDataType;
typedef struct QNode{
struct QNode* _next;
QDataType _data;
}QNode;
typedef struct Queue{
QNode* _front;
QNode* _rear;
int _size;
}Queue;
void queueInit(Queue* q);
QNode* creatNode(QDataType data);
//入队
void queuePush(Queue* q, QDataType data);
//出队
void queuePop(Queue* q);
QDataType queueFront(Queue* q);
QDataType queueBack(Queue* q);
int queueSize(Queue* q);
int queueEmpty(Queue* q);
void queuePrint(Queue* q);
void queuqDestory(Queue* q);
代码实现文件
#include "queue.h"
#include <stdio.h>
#include <stdlib.h>
void queueInit(Queue* q) {
q->_front = q->_rear = NULL;
q->_size = 0;
}
QNode* creatNode(QDataType data) {
QNode* node = (QNode*)malloc(sizeof(QNode));
node->_data = data;
node->_next = NULL;
return node;
}
//队尾入队
//思路:先让尾指针指向node,然后让尾指针向后移动移动一个元素(移动到node的位置);
void queuePush(Queue* q, QDataType data) {
QNode* node = creatNode(data);
if (q->_front == NULL) {
q->_front = q->_rear = node;
}
else {
q->_rear->_next = node;
q->_rear = node;
}
++q->_size;
}
//
//
//头删出队
void queuePop(Queue* q) {
if (q->_front) {
QNode* next = q->_front->_next;
free(q->_front);
q->_front = next;
if (q->_front == NULL) //删除之后是否为空表
q->_rear = NULL;
--q->_size;
}
}
QDataType queueFront(Queue* q) {
return q->_front->_data;
}
QDataType queueBack(Queue* q) {
return q->_rear->_data;
}
int queueSize(Queue* q) {
/*int num = 0;
QNode* cur = q->_front;
while (cur) {
++num;
cur = cur->_next;
}
return num;*/
return q->_size;
}
int queueEmpty(Queue* q) {
if (q->_front == NULL) {
return 1;
}
return 0;
}
void queueDestroy(Queue* q) {
QNode* cur = q->_front;
while (cur) {
QNode* next = cur->_next;
free(next);
cur = cur->_next;
}
q->_front = q->_rear = NULL;
q->_size = 0;
}
测试文件
#include "queue.h"
#include <stdio.h>
#include <stdlib.h>
void test1() {
Queue q;
queueInit(&q);
queuePush(&q, 1);
queuePush(&q, 2);
queuePush(&q, 3);
queuePush(&q, 4);
queuePush(&q, 5);
queuePush(&q, 6);
while (queueEmpty(&q) != 1) {
printf("%d ", queueFront(&q));
queuePop(&q);
}
printf("\n");
}
int main () {
test1();
system("color A");
system ("pause");
return 0;
}
运行结果:
栈的实现(顺序表)
1.栈的基本操作(常用顺序表来实现)
栈是先进后出
实现:顺序表,单链表(头插,头删操作)
常用实现方式: stack的实现通过顺序表来实现,PushBack—>入栈操作 Popback---->出栈操作
顺序表, 单链表—>实现栈都是O(1)操作
遍历方式: 获取栈顶元素来进行判定
函数声明
#pragma once
#include <stdio.h>
#include <stdlib.h>
typedef int Type;
typedef struct Stack{
Type* _array;
size_t _size;
size_t _capacity;
}Stack;
//初始化
void stackInit(Stack* st, size_t n);
//入栈操作
void stackPush(Stack* st, Type data);
//出栈操作
void stackPop(Stack* st);
//获取栈顶元素
//入栈操作
Type stackTop(Stack* st);
//返回栈的大小
size_t stackSize(Stack* st);
//判空操作
int stackEmpyt(Stack* st);
//销毁
void stackDestroy(Stack* st);
实现文件
#include "stack.h"
#include <stdio.h>
#include <stdlib.h>
//初始化
void stackInit(Stack* st, size_t n) {
st->_array = (Type*)malloc(sizeof(int)*n); //申请空间
st->_capacity = n;
st->_size = 0;
}
//入栈操作
void stackPush(Stack* st,Type data) {
//检查容量
if (st->_size == st->_capacity) {
st->_capacity *= 2;
st->_array = (Type*)realloc(st->_array, sizeof(int)*st->_capacity);
}
//尾插操作
st->_array[st->_size++] = data;//代表先给_size的位置先放入元素在进行++操作
}
//出栈操作
void stackPop(Stack* st) {
//尾删操作
if (st->_size) {
--st->_size;
}
}
//获取栈顶元素
//入栈操作
Type stackTop(Stack* st) {
return st->_array[st->_size - 1];
}
//返回栈的大小
size_t stackSize(Stack* st) {
return st->_size;
}
//判空操作
int stackEmpyt(Stack* st) {
if (st->_size == 0) {
return 1;
}
else {
return 0;
}
}
//销毁
void stackDestroy(Stack* st) {
free(st->_array);
st->_array = NULL;
st->_capacity = st->_size = 0;
}
栈和队列常考习题整理
1. 括号匹配问题。
第一种情况:已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false
第二种情况:遍历字符串匹配的过程中,发现栈里没有要匹配的字符。所以return false
第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号return false
那么什么时候说明左括号和右括号全都匹配了呢,就是字符串遍历完之后,栈是空的,就说明全都匹配了。
class Solution {
public:
bool isValid(string s) {
stack<int> st;
for (int i = 0; i < s.size(); i++) {
if (s[i] == '(') st.push(')');
else if (s[i] == '{') st.push('}');
else if (s[i] == '[') st.push(']');
// 第三种情况 是遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号 return false
// // 第二种情况 遍历字符串匹配的过程中,发现栈里没有我们要匹配的字符。所以return false
else if (st.empty() || st.top() != s[i]) return false;
else st.pop(); // st.top() == s[i]
}
// 第一种情况 此时我们已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false,否则就return true
if (st.empty())
return true;
return false;
}
};
2. 用队列实现栈。
栈是一种后进先出的数据结构,元素从顶端入栈,然后从顶端出栈。
队列是一种先进先出的数据结构,元素从后端入队,然后从前端出队。
两个栈实现队列的思想:
使用两个队列实现栈的基本操作 : queue1(真正实现栈功能的操作队列) queue2(作为入栈操作的辅助队列。)
实现步骤:
1.入栈操作, 首先先将元素入队到queue2中, 然后再将queue1原有的元素都导入到queue2中, 此时从queue1中导入到
queue2中的元素排在queue2中的最后,交换queue1和queue2中的元素, 此时queue1中前端和后端分别代表栈顶部和栈底部
class MyStack {
public:
/** Initialize your data structure here. */
MyStack() {
}
queue<int> q1;//真正实现接口操作的队列
queue<int> q2; //辅助队列 作用:元素刚开始都是先放入辅助队列中,然后在交换到真正操作的队列中
/** Push element x onto stack. */
void push(int x) {
q2.push(x); //元素直接放入到辅助队列中
while(!q1.empty()) { //在交换两个内容的时候先判定q1中是否为空队列
q2.push(q1.front());//假如不是空的时候一定要将q1中元素先放入到辅助队列中然后在进行交换操作
q1.pop();
}
swap(q1,q2); //交换两个队列内容的操作
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
int ret=q1.front();//先对队列元素进行标记操作
q1.pop();//出队
return ret;//返回队头元素
}
/** Get the top element. */
int top() {
return q1.front();//队头元素
}
/** Returns whether the stack is empty. */
bool empty() { //判断q1中队列是否为空即可
if (q1.empty())
return true;
return false;
}
};
3. 用栈实现队列。
根据栈的特性得到最新压入的元素必须得放在栈底。因此需要把st1中所有的元素移到st2中,
接着把新元素压入st2。最后把st2中所有的元素弹出,压入到st1中。
class MyQueue {
public:
/** Initialize your data structure here. */
MyQueue() {
}
stack<int> st1;
stack<int> st2;//辅助栈
/** Push element x to the back of queue. */
void push(int x) {
while(!st1.empty()) { //这个操作是实现保证给辅助栈中插入元素的时候st1是空的栈
st2.push(st1.top());
st1.pop();
}
st2.push(x);//辅助栈中直接放入元素----放入元素之前一定要保证将st1中的元素全部导入到了st2中才可以.
while(!st2.empty()) {
st1.push(st2.top());
st2.pop();
}
}
/** Removes the element from in front of queue and returns that element. */
int pop() { //出队操作: 实际上就是栈的顶部元素
int ret=st1.top();
st1.pop();
return ret;
}
/** Get the front element. */
int peek() { //栈的顶部元素
return st1.top();
}
/** Returns whether the queue is empty. */
bool empty() { //判空操作
if (st1.empty())
return true;
return false;
}
};
4. 设计循环队列。
typedef struct {
int* array;//数组
int k;//循坏队列容量大小
int size;
int front; //队头
int rear;//队尾
} MyCircularQueue;
//先创建循环队列
MyCircularQueue* myCircularQueueCreate(int k) {
//先在堆上开辟一个循环队列
MyCircularQueue* mq = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
mq->array = (int*)malloc(sizeof(int)*k);//给循环队列的数组申请空间
mq->k = k;
mq->front = mq->rear = 0;
mq->size = 0;
return mq;
}
//入队操作:实质--尾部元素进行相加即可
//1.判断是否队列已满
//2.直接执行尾插操作--> rear++即可(即尾部元素向后移动)
//3.当移动到最后一个元素的位置的时候要进行重新更新rear,保证始终循环队列的需求
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
if (obj->size == obj->k)
return false;
//尾插操作
obj->array[obj->rear++] = value;
//保证循环结构
if (obj->rear == obj->k)
obj->rear = 0;
obj->size++;
return true;
}
//出队操作:实质--头部元素进行相加即可
//1.判断是否为空队列
//2.直接front++即可
//3.当移动到最后一个元素要进行更新头部
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
if (obj->size == 0)
return false;
++obj->front;
if (obj->front == obj->k)
obj->front = 0;
--obj->size;
return true;
}
//获取头部元素
int myCircularQueueFront(MyCircularQueue* obj) {
if (obj->size == 0)
return -1;
return obj->array[obj->front];
}
//获取尾部元素: 始终得到的是rear的前一个元素
int myCircularQueueRear(MyCircularQueue* obj) {
if (obj->size == 0)
return -1;
//obj->rear有可能到达最后一个元素的位置时会更新,前一个位置前一个队列恰好就会容量k-1的位置元素
if (obj->rear == 0)
return obj->array[obj->k - 1];
return obj->array[obj->rear - 1];
}
//判空操作
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
if (obj->size == 0)
return true;
return false;
}
//判断是否队列已满
bool myCircularQueueIsFull(MyCircularQueue* obj) {
if (obj->size == obj->k)
return true;
return false;
}
//销毁操作
void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->array);
free(obj);
}
C++实现
class MyCircularQueue {
//初始化变量
int* array; //存放于数组中
int capacity;//容量大小
int size;//有效元素的个数
int front;//头部
int rear;//尾部
public:
MyCircularQueue(int k) {
//初始化
array = new int[k];
size = 0;
front = rear = 0;
capacity = k;
}
//入队操作
bool enQueue(int value) {
if (size == capacity)
return false;
array[rear++] = value;
if (rear == capacity)
rear = 0;
++size;
return true;
}
//出队操作
bool deQueue() {
if (size == 0)
return false;
front++;
if (front == capacity)
front = 0;
--size;
return true;
}
//队头元素
int Front() {
if (size == 0)
return -1;
return array[front];
}
//队尾元素
int Rear() {
if (size == 0)
return -1;
if (rear == 0)
return array[capacity - 1];
return array[rear - 1];
}
//判空操作
bool isEmpty() {
if (size == 0)
return true;
return false;
}
//判断是否存满元素
bool isFull() {
if (size == capacity)
return true;
return false;
}
};