栈和队列经典题

实现一个栈,要求实现Push(出栈)、Pop(入栈)、Min(返回最小值)的时间复杂度为O(1)

这道题出栈和入栈都比较好求,关键在于这个返回最小值的时间复杂度,一般来说,要遍历一遍,但是这样时间复杂度就是O(n),和题意不符,这道题的做法是创建一个结构体,这个结构体中保存着入栈元素的大小,也包含着这个栈中最小的元素,然后再创建一个结构体,这个结构体是栈,入栈的时候直接压入结构体,情况如下所示:





test.c

#include"StackAndQueuelnterview.h"
#include<Windows.h>
int main()
{
	Stack s;
	InitStack(&s);
	StackPush(&s, 5);
	StackPush(&s, 5);
	StackPush(&s, 6);
	StackPush(&s, 2);
	StackPop(&s);
	StackPush(&s, 8);
	StackPush(&s, 10);
	StackPush(&s, 50);
	//最小值应该是5
	printf("Minddata is %d", StackMindata(&s));
	system("pause");
	return 0;
}

Stacklnterview.h

#pragma once
#include<stdio.h>
#include<assert.h>
#define MAX_SIZE 100
//封装结构体,最大100个
typedef struct NewData
{
	int data;
	int Mindata;
}Newdata;

typedef struct Stack
{
	Newdata _arr[MAX_SIZE];//栈里放封装好的结构体
	int _size;
}Stack,*PStack;

//初始化
void InitStack(PStack s);
//栈顶插入元素
void StackPush(PStack s, int data);
//出栈
void StackPop(PStack s);
//返回最小元素
int  StackMindata(PStack s);


Stacklnterview.c

#include"StackAndQueuelnterview.h"
//初始化
void InitStack(PStack s)
{
	assert(s);
	s->_size = 0;
}
//栈顶插入元素
void StackPush(PStack s, int data)
{
	assert(s);
	int size = s->_size;
	if (size == MAX_SIZE)
	{
		printf("栈满了");
			return;
	}
	//如果栈是空的,最小的等于第一个元素的值
	if (size == 0)
	{
		s->_arr->data = data;
		s->_arr->Mindata = s->_arr->data;
		
		s->_size++;
		return;
	}
	if ((s->_arr + size -1)->Mindata > data)
	{
		(s->_arr + size)->Mindata = (s->_arr + size)->data = data;
		s->_size++;
		return;
	}
	//压入的元素大于上一个元素的Minddata
	else
	{
		(s->_arr + size)->Mindata = (s->_arr + size-1)->Mindata;
		(s->_arr + size)->data = data;
		 s->_size++;

	}

}
//出栈
void StackPop(PStack s)
{
	assert(s);
	if (s->_size == 0)
	{
		printf("栈为空");
		return;
	}
	s->_size--;
}
//返回最小元素
int  StackMindata(PStack s)
{
	assert(s);
	if (s->_size == 0)
	{
		printf("没有元素");
		return;
	}
	return (s->_arr + (s->_size - 1))->Mindata;
}

///////////////////////////////////////////////////////////队列/////////////////////////////////////////////////////////////////////

使用两个栈实现一个队列

思路:栈是先进后出,队列是先进先出,用两个栈来实现,先把队列的元素加到其中一个栈里,如果满了,就搬移到另外一个栈,这样栈顶元素就是队列的开始位置,以后再往进加队列元素时,先看看栈1满了没,如果没有,放到栈1中,等满了再倒入栈2,下面看图



test.c

#include"StackAndQueuelnterview.h"
//初始化队列
void QueueInit(PQueue q)
{
	assert(q);
	q->S1._size = 0;
	q->S2._size = 0;
}
//入栈
void StackPush(Stack* s, DataType data)
{
	assert(s);
	if (s->_size == MAX_SIZE)
	{
		printf("栈满了");
		return;
	}
	s->_arr[s->_size] = data;
	s->_size++;
	
}
//入队列,入到栈s1
void QueuePush(PQueue q, DataType data)
{
	assert(q);
	if (q->S1._size == MAX_SIZE)
	{
		//搬移必须保证第二个队列为空
		if (q->S2._size == 0)
		{
			while (q->S1._size != 0)
			{
				DataType data = StackTop(&(q->S1));
				StackPop(&(q->S1));
				StackPush(&(q->S2), data);
			}
		}
		else
		{
			printf("s2队列不为空");
		}
	}
	//在s1中加元素
	StackPush(&(q->S1), data);
}
//返回栈顶元素
DataType StackTop(Stack* s)
{
	assert(s);
	if (s->_size == 0)
	{
		printf("栈空了");
		return;
	}
	return s->_arr[s->_size - 1];
}
//出栈
void StackPop(Stack* s)
{
	assert(s);

	if (s->_size == 0)
	{
		printf("栈为空,操作失败!!!\n");
		return;
	}

	s->_size--;
}
//出队列
void QueuePop(PQueue q)
{
	assert(q);
	//s2不为空,直接出,顶为队列头
	if (q->S2._size > 0)
	{
		StackPop(&(q->S2));
		return;
	}
	else
	{
		//如果s1也为空,队列为空
		if (q->S1._size == 0)
		{
			printf("队为空");
			return;
		}

		//s1不为空,将s1倒过来
		else
		{
			while (q->S1._size != 0)
			{
				DataType data = StackTop(&(q->S1));
				StackPop(&(q->S1));
				StackPush(&(q->S2), data);
			}
		}
		//s2的栈顶为队头
		StackPop(&(q->S2));
	}

}
//获取队头元素
DataType QueueFront(PQueue q)
{
	assert(q);
	//s1 and s2 all empty
	if (q->S1._size == 0 && q->S2._size == 0)
	{
		printf("the queue is null");
		return 0;
	}
	if (q->S2._size != 0)
	{
		return StackTop(&(q->S2));
	}
	else
		return q->S1._arr[0];
}
//获取队尾元素
DataType QueueBack(PQueue q)
{
	assert(q);
	//如果s1,s2都是空的,说明队列是空的
	if (q->S1._size == 0 && q->S2._size == 0)
	{
		printf("the queue is null");
		return 0;
	}
	//如果s1不为空,那么队尾就是s1的栈顶,否则,就是s2的栈底
	if (q->S1._size != 0)
		return StackTop(&(q->S1));
	else
		return q->S2._arr[0];

}

StackAndQueueInterview.h

#pragma
#include<stdio.h>
#include<assert.h>

#define MAX_SIZE 9
typedef int DataType;
typedef struct Stack
{
	DataType _arr[MAX_SIZE];
	int _size;
}Stack;

typedef struct Queue
{
	Stack S1;
	Stack S2;

}Queue,*PQueue;

//初始化队列
void QueueInit(PQueue q);
//入栈
void StackPush(Stack* s, DataType data);
//入队列,入到栈s1
void QueuePush(PQueue q, DataType data);
//返回栈顶元素
DataType StackTop(Stack* s);
//出栈
void StackPop(Stack* s);
//出队列
void QueuePop(PQueue q);
//获取队头元素
DataType QueueFront(PQueue q);
//获取队尾元素
DataType QueueBack(PQueue q);

StackAndQueueInterview.c

#include"StackAndQueuelnterview.h"
//初始化队列
void QueueInit(PQueue q)
{
	assert(q);
	q->S1._size = 0;
	q->S2._size = 0;
}
//入栈
void StackPush(Stack* s, DataType data)
{
	assert(s);
	if (s->_size == MAX_SIZE)
	{
		printf("栈满了");
		return;
	}
	s->_arr[s->_size] = data;
	s->_size++;
	
}
//入队列,入到栈s1
void QueuePush(PQueue q, DataType data)
{
	assert(q);
	if (q->S1._size == MAX_SIZE)
	{
		//搬移必须保证第二个队列为空
		if (q->S2._size == 0)
		{
			while (q->S1._size != 0)
			{
				DataType data = StackTop(&(q->S1));
				StackPop(&(q->S1));
				StackPush(&(q->S2), data);
			}
		}
		else
		{
			printf("s2队列不为空");
		}
	}
	//在s1中加元素
	StackPush(&(q->S1), data);
}
//返回栈顶元素
DataType StackTop(Stack* s)
{
	assert(s);
	if (s->_size == 0)
	{
		printf("栈空了");
		return;
	}
	return s->_arr[s->_size - 1];
}
//出栈
void StackPop(Stack* s)
{
	assert(s);

	if (s->_size == 0)
	{
		printf("栈为空,操作失败!!!\n");
		return;
	}

	s->_size--;
}
//出队列
void QueuePop(PQueue q)
{
	assert(q);
	//s2不为空,直接出,顶为队列头
	if (q->S2._size > 0)
	{
		StackPop(&(q->S2));
		return;
	}
	else
	{
		//如果s1也为空,队列为空
		if (q->S1._size == 0)
		{
			printf("队为空");
			return;
		}

		//s1不为空,将s1倒过来
		else
		{
			while (q->S1._size != 0)
			{
				DataType data = StackTop(&(q->S1));
				StackPop(&(q->S1));
				StackPush(&(q->S2), data);
			}
		}
		//s2的栈顶为队头
		StackPop(&(q->S2));
	}

}
//获取队头元素
DataType QueueFront(PQueue q)
{
	assert(q);
	//s1 and s2 all empty
	if (q->S1._size == 0 && q->S2._size == 0)
	{
		printf("the queue is null");
		return 0;
	}
	if (q->S2._size != 0)
	{
		return StackTop(&(q->S2));
	}
	else
		return q->S1._arr[0];
}
//获取队尾元素
DataType QueueBack(PQueue q)
{
	assert(q);
	//如果s1,s2都是空的,说明队列是空的
	if (q->S1._size == 0 && q->S2._size == 0)
	{
		printf("the queue is null");
		return 0;
	}
	//如果s1不为空,那么队尾就是s1的栈顶,否则,就是s2的栈底
	if (q->S1._size != 0)
		return StackTop(&(q->S1));
	else
		return q->S2._arr[0];

}

判断出栈顺序是不是正确

判断的思路:一组是压栈的顺序,另一组是给的出栈的顺序,如果栈是空的,先压栈,然后和给定的出栈顺序第一个比较,如果第一个出栈的字母在栈里没有,就继续按照入栈的顺序往进入,如果有了,然后弹出,比较下一个出栈元素和栈顶是不是相等,如果不是,继续按照给定的顺序压入,以此类推,如果压到头还是没有,就说明出栈顺序是错误的!如果循环能正常结束,就说明是正确的,见图:


test.c

#include"StackAndQueuelnterview.h"

int main()
{
	stack sta;
	StackInit(&sta);
	int a[5] = { 'a','b','c','d','e' };
	int b[5] = { 'c','d','a','b','e' };
	int index = 0;
	int i = 0;
	PrintStack(&sta);
	StackInit(&sta);
	for(i = 0; i < 5; i++ )
	{
		if ((StackEmpty(&sta) != NULL) && (StackTop(&sta) == b[i]))
			StackPop(&sta);
		else  //压入元素
		{
			while (b[i] != a[index])
			{
				StackPush(&sta, a[index]);
				index++;
				if (index == 5)
				{
					printf("失败");
					system("pause");
					return;
				}
			}
			
				index++;
		}
	}
	printf("成功");
	system("pause");
	return 0;
}

StackAndQueuelnterview.h

#pragma once
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#define T  10
#define MAX 100
typedef char DataType;
typedef struct Stack
{
	DataType arr[MAX];
	//int capacity;
	int size;


}stack, *PStack;






// 栈的初始化 
void StackInit(PStack ps);


// 入栈 
void StackPush(PStack ps, DataType data);


// 出栈 
void StackPop(PStack ps);
//
// 获取栈顶元素 
DataType StackTop(PStack ps);


// 获取栈中元素个数 
int StackSize(PStack ps);


// 检测栈是否为空 
int StackEmpty(PStack ps);


void PrintStack(PStack ps);//打印栈


StackAndQueuelnterview.c

#include"StackAndQueuelnterview.h"
// 栈的初始化 
void StackInit(PStack ps)
{
	assert(ps);
	ps->size = 0;
}


//入栈 
void StackPush(PStack ps, DataType data)
{
	assert(ps);
	ps->arr[ps->size] = data;
	ps->size++;
}


// 出栈 
void StackPop(PStack ps)
{
	assert(ps);
	ps->size--;
}


// 获取栈顶元素 
DataType StackTop(PStack ps)
{
	assert(ps);
	return ps->arr[ps->size - 1];

}


//获取栈中元素个数 
int StackSize(PStack ps)
{
	assert(ps);
	return ps->size;
}


//检测栈是否为空 
int StackEmpty(PStack ps)
{
	if (ps->size)
		return 1;
	else
		return 0;


}
void PrintStack(PStack ps)//打印栈
{
	int i = 0;
	for (; i < ps->size; i++)
	{
		printf("%c", ps->arr[i]);
	}
}





<think>嗯,用户想了解队列的数据结构概念及其应用场景,可能是为了考试或者写论述答案。首先,我需要回忆队列的基本定义,确保概念准确。是后进先出(LIFO)的结构,队列是先进先出(FIFO)的。然后要比较它们的异同,比如操作上的区别,比如的pushpop在顶端,队列的enqueuedequeue分别在尾头。 接下来是应用场景,的应用比如函数调用堆、括号匹配、撤销操作;队列的应用比如任务调度、缓冲处理、广度优先搜索。需要具体例子,比如操作系统中的进程调度用队列,编辑器里的撤销用。这部分要结合用户提供的引用,比如引用[2]提到数据存储技术,可能可以关联到实际应用中的实现。 用户提供的引用里,引用[1]提到数据结构目详解,可能需要注意常见错误,比如溢出或者队列空的情况处理。引用[3]讲线程超时,可能队列在任务调度中的应用有关联,但不确定是否直接相关,可能需要谨慎引用。 还要确保回答结构清晰,分点论述。可能用户需要简答论述两种形式,所以先给出概念,再比较异同,最后详细的应用场景。代码示例部分,用户给的例子是Python,所以用Python实现队列的基本操作,比如用列表实现,但要注意线程安全或者效率问,比如用collections.deque实现队列更高效。 需要检查LaTeX格式是否正确,所有行内公式用$...$,独立公式用$$...$$。比如的操作复杂度是$O(1)$,队列的也是$O(1)$,但循环队列可能需要数组实现。这部分可能需要数学表达式,但用户示例中没有复杂的公式,保持简洁。 最后生成相关问,要围绕队列的扩展,比如实现方式、应用实例、复杂度分析等。确保问有助于用户进一步学习或考试准备。注意引用标识要自然添加,比如在讨论括号匹配时引用[^1]的常见错误,或者在数据存储实现时引用[^2]。 现在整理回答结构,先定义队列,再比较,接着应用场景,代码示例,最后相关问。确保每个部分都准确,并且引用恰当的地方。</think>### 队列的概念及应用场景 #### 1. **数据结构概念** - **(Stack)**: 是一种**后进先出(LIFO)**的线性数据结构,仅允许在**同一端(顶)**进行插入(`push`)删除(`pop`)操作。其核心特性为: - 基本操作时间复杂度为$O(1)$; - 典型应用包括函数调用、表达式求值、括号匹配等。 - **队列(Queue)**: 队列是一种**先进先出(FIFO)**的线性数据结构,插入操作(`enqueue`)在**队尾**进行,删除操作(`dequeue`)在**队头**进行。其特点为: - 基本操作时间复杂度为$O(1)$; - 应用场景如任务调度、消息队列、广度优先搜索(BFS)等。 #### 2. **队列的对比** | 特性 | | 队列 | |--------------|------------------------|--------------------------| | 操作端 | 仅顶 | 队头(删除)、队尾(插入)| | 数据顺序 | LIFO | FIFO | | 典型问 | 递归实现、撤销操作 | 多线程任务分发、缓冲处理 | #### 3. **应用场景详解** - **的典型应用**: - **函数调用**:程序执行时保存函数调用上下文,确保返回地址局部变量的正确性[^1]; - **括号匹配**:通过检测表达式中的括号嵌套合法性,例如`((a+b)*c)`; - **撤销操作(Undo)**:编辑器通过记录操作历史,支持反向回退。 - **队列的典型应用**: - **任务调度**:操作系统使用队列管理进程的就绪状态,确保公平性(如轮转调度)[^3]; - **消息队列**:分布式系统中异步处理请求,解耦生产者消费者; - **广度优先搜索(BFS)**:遍历图或树时,按层级访问节点。 #### 4. **代码示例** **的实现(Python)**: ```python class Stack: def __init__(self): self.items = [] def push(self, x): self.items.append(x) def pop(self): return self.items.pop() if self.items else None def is_empty(self): return len(self.items) == 0 ``` **队列的实现(Python)**: ```python from collections import deque class Queue: def __init__(self): self.items = deque() def enqueue(self, x): self.items.append(x) def dequeue(self): return self.items.popleft() if self.items else None ``` #### 5. **关键问与扩展** - **溢出**:递归过深可能导致空间耗尽,需注意递归终止条件; - **循环队列**:通过固定长度数组指针实现队列,避免数据迁移的开销; - **线程安全队列**:多线程环境下需使用锁或原子操作保证一致性。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值