队列和队列的模拟实现以及习题整理

队列实现: (单链表)

队列: 先进先出原则
入队: 尾插
出队: 头删
实现: 顺序表,链表
顺序表: 尾插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;
	}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
西南交通大学的考研数据结构和C语言真题主要涵盖了数据结构和C语言的基本概念、常见算法和数据结构的应用,是考研复习的重点和难点。 数据结构部分的真题主要涉及线性表、栈和队列、链表和树、图和排序等知识点。例如,可能会出现关于数组的插入、删除和查找操作以及对其时间复杂度的分析题目,还可能会要求设计实现单链表、二叉树或图等数据结构,并进行相应的操作和应用。对于这些题目,考生需要熟悉各种数据结构的特点、使用方法和算法,能够分析算法的时间复杂度和空间复杂度,并灵活应用到实际问题。 C语言部分的真题主要考察C语言的基本语法、指针和内存管理、函数和库等方面的知识。可能会出现关于函数的声明和定义、指针的使用、内存动态分配和释放等方面的题目。考生需要对C语言的语法、特性和常用库函数有一定的掌握,能够理解和分析C语言程序的执行过程和内存管理机制。 对于准备西南交通大学考研的考生来说,要复习数据结构和C语言,首先要掌握基础概念和常用算法和数据结构的原理和应用。其次,要多做真题和模拟题,加深对知识的理解和应用。同时,还要关注最新的考研动态和备考资料,及时调整和完善复习计划。通过系统的学习和不断的练习,相信考生一定能够顺利应对西南交通大学考研数据结构和C语言的考试。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值