栈和队列+力扣oj

队列:

队列是一种常见的数据结构,它遵循先进先出(First-In-First-Out,FIFO)的原则。队列通常表示为一个有序的元素列表,新的元素被添加到队列的末尾,而从队列中删除元素时,总是从队列的开头移除。

队列的操作包括两个主要部分:入队(enqueue)和出队(dequeue)。

- 入队:将新的元素添加到队列的末尾。
- 出队:从队列的开头移除并返回元素。

其他常见的队列操作包括:
- 队列大小(size):返回当前队列中的元素个数。
- 队列是否为空(isEmpty):检查队列是否没有任何元素。
- 队列的头部元素(front):返回队列的第一个元素,而不进行出队操作。
- 清空队列(clear):移除队列中的所有元素,使其变为空队列。

队列oj题

例一:队列实现栈

typedef int QDataType;
typedef struct QListNode
{
	struct QListNode* _next;
	QDataType _data;
}QNode;

// 队列的结构 
typedef struct Queue
{
	QNode* _front;//头
	QNode* _rear;//尾
}Queue;


typedef struct 
{
    Queue q1;
    Queue q2;
} MyStack;


void QueueInit(Queue* q)
{
	q->_front = q->_rear = NULL;

}

void QueuePush(Queue* q, QDataType data)
{
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	newnode->_data = data;
	newnode->_next = NULL;
	if (q->_rear == NULL)
	{
		q->_front = q->_rear = newnode;
	}
	else
	{
		q->_rear->_next = newnode;
		q->_rear = newnode;
	}
}

void QueuePop(Queue* q)
{
	if (q->_front->_next == NULL)
	{
		free(q->_front);
		q->_front = q->_rear = NULL;
	}
	else
	{
		QNode* tmp = q->_front->_next;
		free(q->_front);
		q->_front = tmp;
	}


}

QDataType QueueFront(Queue* q)
{
	return q->_front->_data;
}

QDataType QueueBack(Queue* q)
{
	return q->_rear->_data;
}

int QueueSize(Queue* q)
{
	QNode* head = q->_front;
	int size = 0;
	while (head)
	{
		head = head->_next;
		size++;
	}
	return size;
}

int QueueEmpty(Queue* q)
{
	return q->_front == NULL;
}

void QueueDestroy(Queue* q)
{
	QNode* head = q->_front;
	while (head)
	{
		QNode* next = head->_next;
		free(head);
		head = next;
	}
	q->_front = q->_rear = NULL;


}

MyStack* myStackCreate() 
{
  MyStack* _st=(MyStack* )malloc(sizeof(MyStack));
  QueueInit(&_st->q1);
  QueueInit(&_st->q2);

  return _st;
}

void myStackPush(MyStack* obj, int x) 
{
    if(!QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q1,x);
    }
    else
    {
         QueuePush(&obj->q2,x);
    }

}

int myStackPop(MyStack* obj)
{//预设q1为空
     Queue* empty =&obj->q1;
      Queue* fall=&obj->q2;
    if(!QueueEmpty(&obj->q1))
    {
        empty=&obj->q2;
        fall=&obj->q1;
    }
    //将非空队列中的最后一个数前的所有元素导入空队列中
    while(QueueSize(fall)>1)
    {
        QueuePush(empty, QueueFront(fall));
        QueuePop(fall);
    }
    int top=QueueFront(fall);
    QueuePop(fall);
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) 
{
QueueDestroy(&obj->q1);
QueueDestroy(&obj->q2);
free(obj);
}

/**
 * Your MyStack struct will be instantiated and called as such:
 * MyStack* obj = myStackCreate();
 * myStackPush(obj, x);
 
 * int param_2 = myStackPop(obj);
 
 * int param_3 = myStackTop(obj);
 
 * bool param_4 = myStackEmpty(obj);
 
 * myStackFree(obj);
*/

代码思路简述:目标栈含有两个队列,为了符合栈先入先出的性质,所以使用两队列互相移动数据。数据进入非空队列,出队列为非空队列的前n-1个数据,腾挪至另一个空队列,然后只剩1个数据的队列出数据,即可做到先入后出。

例二:栈实现队列

typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;

typedef struct
{
	ST s1;
	ST s2;
} MyQueue;

void STInit(ST* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->capacity = 0;
	ps->top = 0;
}

void STDestroy(ST* ps)
{
	assert(ps);

	free(ps->a);
	ps->a = NULL;
	ps->top = ps->capacity = 0;
}

void STPush(ST* ps, STDataType x)
{
	assert(ps);
	// 11:40
	if (ps->top == ps->capacity)
	{
		int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newCapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}

		ps->a = tmp;
		ps->capacity = newCapacity;
	}

	ps->a[ps->top] = x;
	ps->top++;
}

void STPop(ST* ps)
{
	assert(ps);

	// 
	assert(ps->top > 0);

	--ps->top;
}

STDataType STTop(ST* ps)
{
	assert(ps);

	// 
	assert(ps->top > 0);

	return ps->a[ps->top - 1];
}

int STSize(ST* ps)
{
	assert(ps);

	return ps->top;
}

bool STEmpty(ST* ps)
{
	assert(ps);

	return ps->top == 0;
}



MyQueue* myQueueCreate()
{
	MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
	STInit(&obj->s1);
	STInit(&obj->s2);
	return obj;
}

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

int myQueuePeek(MyQueue* obj)
{
	if (STEmpty(&obj->s2))
	{
		while (!(STEmpty(&obj->s1)))
		{
			STPush(&obj->s2, STTop(&obj->s1));
			STPop(&obj->s1);
		}
	}
	return STTop(&obj->s2);
}


int myQueuePop(MyQueue* obj)
{
	int fount = myQueuePeek(obj);
	STPop(&obj->s2);
	return fount;
}


bool myQueueEmpty(MyQueue* obj)
{
	return STEmpty(&obj->s1) && STEmpty(&obj->s2);

}

void myQueueFree(MyQueue* obj)
{
	STDestroy(&obj->s2);
	STDestroy(&obj->s1);
	free(obj);
	obj = NULL;
}

/**
 * Your MyQueue struct will be instantiated and called as such:
 * MyQueue* obj = myQueueCreate();
 * myQueuePush(obj, x);
 
 * int param_2 = myQueuePop(obj);
 
 * int param_3 = myQueuePeek(obj);
 
 * bool param_4 = myQueueEmpty(obj);
 
 * myQueueFree(obj);
*/

解题思路:为实现队列的先入先出,需要两个栈,数据先入栈,再将含有数据栈的n个数据出栈,达到数据倒置的效果,再将数据栈出栈,达到先入先出的效果

例三:设计循环队列




typedef struct {
    int *a;
    int front ;
    int rear;
    int k;
    
} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k) {
     MyCircularQueue *obj=( MyCircularQueue*)malloc(sizeof( MyCircularQueue));
     obj->a=(int *)malloc(sizeof(int)*(k+1));
     obj->front=obj->rear=0;
     obj->k=k;
     return obj;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) 
{
 return obj->front==obj->rear;

}
bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return (obj->rear+1)%(obj->k+1)==obj->front;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
  if(myCircularQueueIsFull(obj))
  return false;  
  obj->a[obj->rear]=value;
  obj->rear++;
  obj->rear%=(obj->k+1);

  return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj) )
    return false;
    ++obj->front;
    obj->front%=(obj->k+1);
    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->rear+obj->k)%(obj->k+1)];
}





void myCircularQueueFree(MyCircularQueue* obj) {
    
    free(obj->a);
    free(obj);
}

/**
 * Your MyCircularQueue struct will be instantiated and called as such:
 * MyCircularQueue* obj = myCircularQueueCreate(k);
 * bool param_1 = myCircularQueueEnQueue(obj, value);
 
 * bool param_2 = myCircularQueueDeQueue(obj);
 
 * int param_3 = myCircularQueueFront(obj);
 
 * int param_4 = myCircularQueueRear(obj);
 
 * bool param_5 = myCircularQueueIsEmpty(obj);
 
 * bool param_6 = myCircularQueueIsFull(obj);
 
 * myCircularQueueFree(obj);
*/

注意点:队列大小需+1,用作循环。数组尾部数据下标特殊大小处理:rear%=(k+1)

取余可使尾部下标达到循环的效果。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值