数据结构——3道栈和队列OJ题

目录

习题1 用队列实现栈

队列的实现

通过队列实现栈 

 结构体的建立

 初始化

压栈 

 出栈

 返回栈顶

 判断是否为空

 销毁空间

 用队列实现栈 

 栈的实现

 结构体创建

 结构体的初始化

 元素入队

 将Push元素倒到Pop中

返回头元素然后移除

 返回头元素

 判断是否为空

 空间的销毁

设计循环队列

 结构体的定义

 初始化

判断是否为空 

判断是否满了 

 在队列内插入元素

删除队列内元素 

 返回队首元素

 获得队尾元素

 空间释放


习题1 用队列实现栈

225. 用队列实现栈 - 力扣(LeetCode)

1.把有数据队列的内容,传到没数据的队列中,传一个之后,再原队列中删一个

2.等q1中剩一个元素的时候,让这个元素出队

这样就可以达到栈的效果,1,2,3,4,5,让5先出栈,之后再按照同样的方法把q1看作空(压栈的时候要往有元素的队里压),开始倒数据即可 

 

 

队列的实现

typedef int QDataType;
typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType data;
}QNode;
typedef struct Queue
{
	QNode *head;
	QNode* tail;
	size_t size;
}Queue;
void QueueInit(Queue* pq);
void QueueDestory(Queue* pq);
void QueuePush(Queue *pq, QDataType x);
void QueuePop(Queue* pq);
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);
bool QueueEmpty(Queue* pq);
int QueueSize(Queue* pq);
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->head = pq->tail = NULL;
	pq->size = 0;
}
void QueueDestory(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	while (cur)
	{
		QNode* del = cur;
		cur = cur->next;
		free(del);
		del = NULL;
	}
	pq->head = pq->tail = NULL;
}
void QueuePush(Queue* pq, QDataType x)
{

	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	assert(newnode);
	newnode->data = x;
	newnode->next = NULL;
	if (pq->tail == NULL)
	{
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = pq->tail->next;
	}
	pq->size++;
}
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}//如果只剩一个节点,单独处理,防止tail变为野指针
	else
	{
		QNode* cur = pq->head;
		pq->head = pq->head->next;
		free(cur);
		cur = NULL;
	}
	pq->size--;
}
QDataType QueueFront(Queue* pq)//取头数据
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->head->data;
}
QDataType QueueBack(Queue* pq)//取尾数据
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->tail->data;
}
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->head==NULL && pq->tail==NULL;
}
int QueueSize(Queue* pq)
{
	return pq->size;
}

通过队列实现栈 

 结构体的建立

typedef struct {
Queue q1; //建立俩个
Queue q2;
} MyStack;
//也可用Queue*,但是这样的话要用malloc给q1和q2开辟空间

 初始化

MyStack* myStackCreate() {
    MyStack*obj=(MyStack*)malloc(sizeof(MyStack));
     QueueInit(&obj->q1);
      QueueInit(&obj->q2);
      return obj;
}//直接传参即可

压栈 

void myStackPush(MyStack* obj, int x) {
    if(!QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q1,x);
    }//如果q1不是空,把元素压到q1
    else
    {
         QueuePush(&obj->q2,x);
    }
}

 出栈

int myStackPop(MyStack* obj) {
   Queue *empty=&obj->q1;//假设q1为空
    Queue *noempty=&obj->q2;//假设q2不是空
    if(!QueueEmpty(&obj->q1))
    {
        noempty=&obj->q1;
        empty=&obj->q2;
   
 while(QueueSize(noempty)>1)         //将有元素的队列的数据,倒到只剩最后一个元素
 {
     QueuePush(empty,QueueFront(noempty));
     QueuePop(noempty);
 }
int top=QueueFront(noempty);//该元素就是栈顶
QueuePop(noempty);
return top;//返回栈顶
}

 返回栈顶

int myStackTop(MyStack* obj) {
if(!QueueEmpty(&obj->q1))
{ 
   return QueueBack(&obj->q1);
}
else
{
return QueueBack(&obj->q2);
}
}//直接调用返回队尾的函数即可

 判断是否为空

bool myStackEmpty(MyStack* obj) {
return QueueEmpty(&obj->q1)&&QueueEmpty(&obj->q2);
}

 销毁空间

void myStackFree(MyStack* obj) {
QueueDestory(&obj->q1);
QueueDestory(&obj->q2);
free(obj);
}

这里不能直接free(obj),因为q1和q2是链表,链表的内存不连续,如果释放掉boj,则q1和q2没有释放,会造成内存泄漏

 用队列实现栈 

 232. 用栈实现队列 - 力扣(LeetCode)

 若队列中是1 2 3 4 5,则按照栈的规则,此时出栈顺序应该是 5 4 3 2 1,我们可以用俩个队列来实现栈

1.把PushST里面的数据倒到PopST

2.出栈的时候,我们只需要出PopST里面的元素就可以,当有元素要填充时,填充到PushST就行

 栈的实现

typedef int STDdtaTtype;
typedef struct Stcak
{
	STDdtaTtype* data;
	int top;
	int capacity;
}ST;
void StackInit(ST* ps);
void StackDestory(ST* ps);
void StackPush(ST* ps, STDdtaTtype x);
void StackPop(ST* ps);
bool StackEmpty(ST* ps);
int StackSize(ST* ps);
STDdtaTtype StackTop(ST* ps);
void StackInit(ST* ps)
{
	assert(ps);
	ps->data = NULL;
	ps->capacity = ps->top = 0;
}
void StackDestory(ST* ps)
{
	assert(ps);
	free(ps->data);
	ps->capacity = ps->top = 0;
	ps->data = NULL;
}
void StackPush(ST* ps, STDdtaTtype x)//注意要看top的位置是0还是-1
{
	assert(ps);
	int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
	if (ps->capacity == ps->top)//判断是否满了
	{
		STDdtaTtype* tmp = realloc(ps->data, sizeof(ps) * newcapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);

		}
		ps->data = tmp;
		ps->capacity = newcapacity;
	}
	ps->data[ps->top] = x;
	ps->top++;
}
void StackPop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	--ps->top;
}
STDdtaTtype StackTop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	return ps->data[ps->top - 1];
}
bool StackEmpty(ST* ps)//判断是否为空栈
{
	assert(ps);
	return ps->top == 0;
}
int StackSize(ST* ps)
{
	assert(ps);
	return ps->top;
}

 结构体创建

typedef struct {
ST PushST;
ST PopST;
} MyQueue;

 结构体的初始化

MyQueue* myQueueCreate() {
MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));
StackInit(&obj->PushST);
StackInit(&obj->PopST);
return obj;
} 

 元素入队

void myQueuePush(MyQueue* obj, int x) {
StackPush(&obj->PushST,x);
}

 将Push元素倒到Pop中

void PushSTTOPopsT(MyQueue* obj)
{
 if(StackEmpty(&obj->PopST))//如果Pop栈内为空,并且Push不为空就给元素
 {
     while(!StackEmpty(&obj->PushST))//当Push不为空
     {
         StackPush(&obj->PopST,StackTop(&obj->PushST));
         StackPop(&obj->PushST);
     }
 }
} 

返回头元素然后移除

int myQueuePop(MyQueue* obj) {
PushSTTOPopsT(obj);
int front=StackTop(&obj->PopST);
StackPop(&obj->PopST);
return front;
}

 返回头元素

int myQueuePeek(MyQueue* obj) {
    PushSTTOPopsT(obj);
return StackTop(&obj->PopST);
}

 判断是否为空

bool myQueueEmpty(MyQueue* obj) {
    return StackEmpty(&obj->PopST)&&StackEmpty(&obj->PushST);

}

 空间的销毁

void myQueueFree(MyQueue* obj) {
StackDestory(&obj->PushST);
StackDestory(&obj->PopST);
free(obj);
}

设计循环队列

622. 设计循环队列 - 力扣(LeetCode)

 ​​​​​​​

 

 

 这里采用数组实现(链表有缺点后面会讲到),front指向首元素,back指向最后元素的下一个空间,空间大小为4,多开辟一个空间,即总共开辟五个空间,使得back+1的位置是front

 结构体的定义

typedef struct {
    int *a;
    int front;
    int back;
int N; //用来统计空间的总个数
} MyCircularQueue;

 初始化

MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue*obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
   obj->a=(int *)malloc(sizeof(int)*(k+1)); //多开辟一个空间
   obj->back=obj->front=0;
   obj->N=k+1;
   return obj;
}

判断是否为空 

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->back==obj->front;
}//当back==front时,就是空

判断是否满了 

 元素满了之后back指向红框,back+1,back指向数组外,此时让back%N,back就会回到首元素位置

 

 

bool myCircularQueueIsFull(MyCircularQueue* obj) {
 return (obj->back+1)%obj->N==obj->front;
}//当back的下一个位置是front时候是满

 在队列内插入元素

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if (myCircularQueueIsFull(obj))
    return false; //如果满了则退出
    obj->a[obj->back]=value;
    obj->back=(obj->back+1)%obj->N; //插入之后,back要走到下一个位置
    return true;
}

 

删除队列内元素 

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
 if(myCircularQueueIsEmpty(obj))
 return false;
obj->front++;
obj->front=obj->front%obj->N; //跟back一样,要防止越界
 return true;
}

 返回队首元素

int myCircularQueueFront(MyCircularQueue* obj) {
 if( myCircularQueueIsEmpty(obj))
 return -1;
 else
 return obj->a[obj->front];
} //如果不为空,返回队首元素

 获得队尾元素

int myCircularQueueRear(MyCircularQueue* obj) {
 if(myCircularQueueIsEmpty(obj))
 return -1;
 else
 return obj->a[(obj->back-1+obj->N)%obj->N];
}

 

 back的上一个位置就是队尾元素,队back-1即可,但是存在一个问题

 当back位于该位置时,back-1就是-1,此时我们可以(back-1+N)%N,使back回到最后一个位置,不用链表实现该题是因为,当获取back所在元素时,链表需要遍历,而数组可以直接访问

小练习题:

5.现有一循环队列,其队头指针为front,队尾指针为rear;循环队列长度为N-1。其队内有效长度为?(假设 队头不存放数据)

A (rear - front + N) % N + 1

B (rear - front + N) % N

C ear - front) % (N + 1)

D (rear - front + N) % (N - 1)

选B,

 空间释放

 

void myCircularQueueFree(MyCircularQueue* obj) {
free(obj->a); //先释放数组空间,再释放给结构体创建的空间
free(obj);
}

 

 

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

头发没有代码多

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值