1.2 LeetCode总结(线性表)_队列类

编程总结

每每刷完一道题后,其思想和精妙之处没有地方记录,本篇博客用以记录刷题过程中的遇到的算法和技巧

232. 用栈实现队列

思路:

在这里插入图片描述

要点就是,先要有栈的数据结构及其实现,然后用两个栈,一个作in stack,一个作out stack来实现队列的先入先出:
a. 进队列,都默认进到 in stack里;
b. 查队列首元素,要求先入先出,那就得先将 in stack 的数据都放到 out stack 里去,这时 out stack 里的top元素就是队列要出的元素;
c. 出队列时,先判断 out stack是否为空,为空则in2out搬运,否则,直接出out stack的top即可;

/*
1.两个type为int的数组(栈),大小为100
  第一个栈stackIn用来存放数据,第二个栈stackOut作为辅助用来输出数据
2.两个指针stackInTop和stackOutTop,分别指向栈顶
*/
typedef struct {
   
   
    int stackInTop, stackOutTop;
    int stackIn[100], stackOut[100];
} MyQueue;
/*
1.开辟一个队列的大小空间
2.将指针stackInTop和stackOutTop初始化为0
3.返回开辟的队列
*/
MyQueue *myQueueCreate() {
   
   
    MyQueue *queue = (MyQueue *)malloc(sizeof(MyQueue));
    queue->stackInTop = 0;
    queue->stackOutTop = 0;
    return queue;
}
/*
将元素存入第一个栈中,存入后栈顶指针+1
*/
void myQueuePush(MyQueue *obj, int x)
{
   
   
    obj->stackIn[(obj->stackInTop)++] = x;
}
/*
1.若输出栈为空且当第一个栈中有元素(stackInTop>0时),将第一个栈中元素复制到第二个栈中(stackOut[stackTop2++] = stackIn[--stackTop1])
2.将栈顶元素保存
3.当stackTop2>0时,将第二个栈中元素复制到第一个栈中(stackIn[stackTop1++] = stackOut[--stackTop2])
*/
int myQueuePop(MyQueue *obj)
{
   
   
    //优化:复制栈顶指针,减少对内存的访问次数
    int stackInTop  = obj->stackInTop;
    int stackOutTop = obj->stackOutTop;
    //若输出栈为空
    if (stackOutTop == 0) {
   
   
        //将第一个栈中元素复制到第二个栈中
        while (stackInTop > 0) {
   
   
            obj->stackOut[stackOutTop++] = obj->stackIn[--stackInTop];
        }
    }
    //将第二个栈中栈顶元素(队列的第一个元素)出栈,并保存
    int top = obj->stackOut[--stackOutTop];
    //将输出栈中元素放回输入栈中
    while (stackOutTop > 0) {
   
   
        obj->stackIn[stackInTop++] = obj->stackOut[--stackOutTop];
    }
    //更新栈顶指针
    obj->stackInTop  = stackInTop;
    obj->stackOutTop = stackOutTop;
    //返回队列中第一个元素
    return top;
}
//返回输入栈中的栈底元素
int myQueuePeek(MyQueue *obj)
{
   
   
    return obj->stackIn[0];
}
//若栈顶指针均为0,则代表队列为空
bool myQueueEmpty(MyQueue *obj)
{
   
   
    return (obj->stackInTop == 0) && (obj->stackOutTop == 0);
}
//将栈顶指针置0
void myQueueFree(MyQueue *obj)
{
   
   
    obj->stackInTop  = 0;
    obj->stackOutTop = 0;
}

225. 用队列实现栈

思路:

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。
实现 MyStack 类:
void push(int x) 将元素 x 压入栈顶。
int pop() 移除并返回栈顶元素。
int top() 返回栈顶元素。
boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。
注意:
你只能使用队列的标准操作 —— 也就是 push to back、peek/pop from front、size 和 is empty 这些操作。
你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
示例:
输入:
[“MyStack”, “push”, “push”, “top”, “pop”, “empty”]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 2, 2, false]
解释:
MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.top(); // 返回 2
myStack.pop(); // 返回 2
myStack.empty(); // 返回 False
提示:
1 <= x <= 9
最多调用100 次 push、pop、top 和 empty
每次调用 pop 和 top 都保证栈不为空

#define MAX_NUN     1024
typedef struct {
   
   
	int head;
	int tail;
	int size; // 计算队列元素个数
	int data[MAX_NUN];
} Queue_t;
bool QueueIsEmpty(Queue_t *queue)
{
   
   
	return (queue->head == queue->tail);
}
bool QueueIsFull(Queue_t *queue)
{
   
   
	return (((queue->tail + 1) % queue->size) == queue->head);
}
bool QueuePush(Queue_t *queue, int value) {
   
   
	if (QueueIsFull(queue)) {
   
   
		return false;
	}
	queue->data[queue->tail] = value;  // 先入队
	queue->tail = (queue->tail + 1) % queue->size; // tail再移动,队尾元素为tail-1.
	return true;
}
int QueueFront(Queue_t *queue)
{
   
   
	if (QueueIsEmpty(queue)) {
   
   
		return -1;
	}
	return queue->data[queue->head];
}
int QueueTail(Queue_t *queue)
{
   
   
	if (QueueIsEmpty(queue)) {
   
   
		return -1;
	}
	return queue->data[(queue->tail - 1 + queue->size) % queue->size];
}
bool QueuePop(Queue_t *queue, int *value)
{
   
   
	if (QueueIsEmpty(queue)) {
   
   
		return false;
	}
	*value = queue->data[queue->head];
	queue->head = (queue->head + 1) % queue->size;
	return true;
}
Queue_t *QueueCreate(int size)
{
   
   
	Queue_t *queue = (Queue_t *)malloc(sizeof(Queue_t));
	queue->tail = 0;
	queue->head = 0;
	queue->size = size;
	memset(queue->data, 0, sizeof(int) * (MAX_NUN));
	return queue;
}
void QueueFree(Queue_t *queue)
{
   
   
	free(queue);
	queue = NULL;
}
/*---------------------两个队列实现栈---------------------*/
typedef struct {
   
   
	Queue_t *queueA;
	Queue_t *queueB;
} MyStack;
// Initialize your data structure here.
MyStack *myStackCreate() {
   
   
	MyStack *stack = (MyStack *)malloc(sizeof(MyStack));
	stack->queueA = QueueCreate(20);
	stack->queueB = QueueCreate(20);
	return stack;
}
// Returns whether the stack is empty.
bool myStackEmpty(MyStack *queue) {
   
   
	return (QueueIsEmpty(queue->queueA) && QueueIsEmpty(queue->queueB));
}
// Returns whether the stack is empty.
bool myStackFull(MyStack *queue) {
   
   
	return (QueueIsFull(queue->queueA) || QueueIsFull(queue->queueB));
}
// Push element x onto stack. 
void myStackPush(MyStack *queue, int x)
{
   
   
	if (myStackFull(queue))
		return;
	Queue_t *enQueue = NULL;
	if (!QueueIsEmpty(queue->queueA)) {
   
   
		enQueue = queue->queueA;
	}
	else {
   
   
		enQueue = queue->queueB;
	}
	QueuePush(enQueue, x);
}
// Removes the element on top of the stack and returns that element. 
int myStackPop(MyStack *queue)
{
   
   
	if (myStackEmpty(queue)) {
   
   
		return -1;
	}
	int data;
	Queue_t *enQueue = NULL;
	Queue_t *deQueue = NULL;
	Queue_t *tmpQueue = NULL;
	if (!QueueIsEmpty(queue->queueA)) {
   
   
		deQueue = queue->queueA;  // queueA A队列出数据
		enQueue = queue->queueB;  // queueB B队列收数据
	}
	else {
   
   
		deQueue = queue->queueB;
		enQueue = queue->queueA;
	}
	while (deQueue->tail != deQueue->head) {
   
   
		printf("\n");
		QueuePop(deQueue, &data);   // 队列1出数据,队列2收数据
		if (!QueueIsEmpty(deQueue)) {
   
    // 队列1出完最后一个元素,队列2不接收,直接作为最后一个输出,它就是栈的Top元素
			QueuePush(enQueue, data);
		}
	}
	printf("tail is %d, head is %d\n", deQueue->tail, deQueue->head);
	return data;
}
// Get the top element. 
int myStackTop(MyStack *queue)
{
   
   
	if (myStackEmpty(queue)) {
   
   
		return -1;
	}
	Queue_t *enQueue = NULL;
	Queue_t *deQueue = NULL;
	int data;
	if (!QueueIsEmpty(queue->queueA)) {
   
   
		deQueue = queue->queueA;
		enQueue = queue->queueB;
	}
	else {
   
   
		deQueue = queue->queueB;
		enQueue = queue->queueA;
	}
	while (deQueue->tail != deQueue->head) {
   
   
		QueuePop(deQueue, &data);
		QueuePush(enQueue, data);
	}
	return data;
}
void myStackFree(MyStack *queue) {
   
   
	QueueFree(queue->queueA);
	QueueFree(queue->queueB);
	free(queue);
}

队列的典型应用:广度优先遍历
有两种通用的遍历树的策略:

1.深度优先搜索(DFS)
在这个策略中,我们采用深度作为优先级,以便从跟开始一直到达某个确定的叶子,然后再返回根到达另一个分支。
深度优先搜索策略又可以根据根节点、左孩子和右孩子的相对顺序被细分为先序遍历,中序遍历和后序遍历。

2.宽度优先搜索(BFS)
我们按照高度顺序一层一层的访问整棵树,高层次的节点将会比低层次的节点先被访问到。

102. 二叉树的层次遍历

思路:层序遍历和BFS很配哦

给定一个二叉树,返回其按层次遍历的节点值。 (即逐层地,从左到右访问所有节点)。
在这里插入图片描述
二叉树的层次遍历使用的更多的是利用队列的性质实现BFS,广度优先遍历:

int **levelOrder(struct TreeNode *root, int *returnSize, int **returnColumnSizes)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值