栈和队列OJ题

1. 括号匹配问题

oj链接

思路分析:

如果有左括号就进栈如果不是先判断栈里面是否为空如果为空返回false,如果不为空就进行匹配

如果匹配不成功返回false反之继续下一个判断

typedef char STDataType;
typedef struct Stack
{
	STDataType* _a;
	int _top;		// 栈顶
	int _capacity;  // 容量 
}Stack;

// 初始化栈 
void StackInit(Stack* ps)
{
	assert(ps);
	ps->_a = NULL;
	ps->_capacity = ps->_top = 0;
}
// 入栈 
void StackPush(Stack* ps, STDataType data)
{
	assert(ps);
	//判断是否需要扩容
	if (ps->_top == ps->_capacity)
	{
		int newcapacity = ps->_capacity == 0 ? 4 : 2 * ps->_capacity;
		STDataType* result = (STDataType*)realloc(ps->_a,newcapacity *sizeof(STDataType));
		if (result == NULL)
		{
			perror("stackpop");
			return;
		}
		ps->_capacity = newcapacity;
		ps->_a = result;
	}
	ps->_a[ps->_top++] =  data;
}
// 出栈 
void StackPop(Stack* ps)
{
	assert(ps && ps->_top);
	ps->_top--;
}
// 获取栈顶元素 
STDataType StackTop(Stack* ps)
{
	assert(ps && ps->_top);
	return ps->_a[ps->_top - 1];
}
// 获取栈中有效元素个数 
int StackSize(Stack* ps)
{
	assert(ps);
	return ps->_top;
}
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
bool StackEmpty(Stack* ps)
{
	return ps->_top == 0;
}
// 销毁栈 
void StackDestroy(Stack* ps)
{
	assert(ps);
	free(ps->_a);
	ps->_a = NULL;
	ps->_capacity = ps->_top = 0;
}
bool isValid(char* s) 
{
	Stack c;
	StackInit(&c);
	while (*s!='\0')
	{
		if (*s == '[' || *s == '{' || *s == '(')
		{
			StackPush(&c, *s);
		}
		else
		{
			if (StackEmpty(&c))
			{
				return false;
			}
			else
			{
				char x = StackTop(&c);
				StackPop(&c);
				if (x == '(' && *s != ')'
					|| x == '[' && *s != ']'
					|| x == '{' && *s != '}')
				{
					return false;
				}
			}
		}
		s++;
    }
	if (StackEmpty(&c))
	{
		return true;
	}
	else
	{
		return false;
	}
}

2. 用队列实现栈

oj链接

思路分析:

我们入栈时应入非空队列,出栈时把非空队列从队头出进入另一个空队列直到非空数列剩下一个然后pop非空数列就完成了出栈。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>
typedef int QDataType;
typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType data;
}QNode;
//这里我们用一个结构体存队列的头指针和尾指针
//这样就避免我们想要改变指向头结点的指针时就不用传入二级指针
typedef struct Queue
{
	QNode* phead;
	QNode* ptail;
	int size;
}Queue;
// 初始化队列 
void QueueInit(Queue* q);
// 队尾入队列 
void QueuePush(Queue* q, QDataType data);
// 队头出队列 
void QueuePop(Queue* q);
// 获取队列头部元素 
QDataType QueueFront(Queue* q);
// 获取队列队尾元素 
QDataType QueueBack(Queue* q);
// 获取队列中有效元素个数 
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q);
// 销毁队列 
void QueueDestroy(Queue* q);
// 初始化队列 
void QueueInit(Queue* q)
{
	assert(q);
	q->phead = NULL;
	q->ptail = NULL;
	q->size = 0;
}
// 队尾入队列 
void QueuePush(Queue* q, QDataType data)
{
	assert(q);
	//入之前现申请一个节点
	QNode* pcur = (QNode*)malloc(sizeof(QNode));
	if (pcur == NULL)
	{
		perror("queuepush");
		return;
	}
	pcur->next = NULL;
	pcur->data = data;
	//进行尾插
	if (q->ptail == NULL)
	{
		q->phead = q->ptail = pcur;
	}
	else
	{
		q->ptail->next = pcur;
		q->ptail = pcur;
	}
	q->size++;
}
// 队头出队列 
void QueuePop(Queue* q)
{
	assert(q);
	//这里我们要判断一下里面有几个节点如果就一个结点
	//我们进行头删就会使ptail变为野指针因为一个节点
	//此时的头尾指针指向同一个节点
	if (q->size == 1)
	{
		free(q->phead);
		q->phead = q->ptail = NULL;
	}
	else
	{
		QNode* pnext = q->phead->next;
		free(q->phead);
		q->phead = pnext;
	}
	q->size--;
}
// 获取队列头部元素 
QDataType QueueFront(Queue* q)
{
	assert(q);
	assert(q->phead);
	return q->phead->data;
}
// 获取队列队尾元素 
QDataType QueueBack(Queue* q)
{
	assert(q && q->ptail);
	return q->ptail->data;
}
// 获取队列中有效元素个数 
int QueueSize(Queue* q)
{
	assert(q);
	return q->size;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q)
{
	return q->size == 0;
}
// 销毁队列 
void QueueDestroy(Queue* q)
{
	QNode* pcur = q->phead;
	while (pcur)
	{
		QNode* pnext = pcur->next;
		free(pcur);
		pcur = pnext;
	}
	q->ptail = q->phead = NULL;
	q->size = 0;

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


MyStack* myStackCreate() {
	MyStack* s = (MyStack*)malloc(sizeof(MyStack));
	QueueInit(&(s->q1));
	QueueInit(&(s->q2));
	s->size = 0;
	return s;
}

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

int myStackPop(MyStack* obj) {
	Queue* empty = &obj->q1;
	Queue* noempty = &obj->q2;
	if (QueueEmpty(&obj->q2))
	{
		empty = &obj->q2;
	}
	if (!QueueEmpty(&obj->q1))
	{
		noempty = &obj->q1;
	}
	while (QueueSize(noempty) > 1)
	{
		int x = QueueFront(noempty);
		QueuePop(noempty);
		QueuePush(empty, x);
	}
	int res = QueueFront(noempty);
	QueuePop(noempty);
	return res;
}

int myStackTop(MyStack* obj) {

	if (!QueueEmpty(&(obj->q1)))
	{
		return QueueBack(&(obj->q1));
	}
	else
	{
		return QueueBack(&(obj->q2));
	}
}

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

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

3. 用栈实现队列

oj链接

思路分析:

s1用来入数据s2用来出数据,出队时如果s2空先把s1数据进来在出栈反之直接对s2进行出栈操作

注意在获取队头数据我们如果s2为空先把s1倒进来此时s2的栈顶数据就是队头数据,反之直接取s2的栈顶数据就可以了。

#define _CRT_SECURE_NO_WARNINGS
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// 支持动态增长的栈
typedef char STDataType;
typedef struct Stack
{
	STDataType* _a;
	int top;		// 栈顶
	int capacity;  // 容量 
}Stack;
// 初始化栈 
void StackInit(Stack* ps)
{
	assert(ps);
	ps->capacity = 0;
	ps->top = 0;
	ps->_a = NULL;
}
// 入栈 
void StackPush(Stack* ps, STDataType data)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		int newcapccity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		STDataType* ans = (STDataType*)realloc(ps->_a, newcapccity * sizeof(STDataType));
		if (ans == NULL)
		{
			perror("realloc");
			return;
		}
		ps->capacity = newcapccity;
		ps->_a = ans;
	}
	ps->_a[(ps->top)++] = data;
}
// 出栈 
void StackPop(Stack* ps)
{
	assert(ps && ps->top);
	ps->top--;
}
// 获取栈顶元素 
STDataType StackTop(Stack* ps)
{
	assert(ps && ps->top);
	return  ps->_a[ps->top - 1];

}
// 获取栈中有效元素个数 
int StackSize(Stack* ps)
{
	assert(ps);
	return ps->top;
}
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(Stack* ps)
{
	assert(ps);
	return ps->top == 0;
}
// 销毁栈 
void StackDestroy(Stack* ps)
{
	assert(ps);
	free(ps->_a);
	ps->_a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}
typedef struct {
	Stack s1;
	Stack s2;
} MyQueue;


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

void myQueuePush(MyQueue* obj, int x) {
	//s1来入队列s2出队列
	StackPush(&obj->s1, x);
}

int myQueuePop(MyQueue* obj) {
	if (StackEmpty(&obj->s2))
	{
		while (StackSize(&obj->s1))
		{
			int x = StackTop(&obj->s1);
			StackPop(&obj->s1);
			StackPush(&obj->s2, x);
		}
	}
		int res = StackTop(&obj->s2);
		StackPop(&obj->s2);
		return res;
}

int myQueuePeek(MyQueue* obj) {
	if (StackEmpty(&obj->s2))
	{
		while (StackSize(&obj->s1))
		{
			int x = StackTop(&obj->s1);
			StackPop(&obj->s1);
			StackPush(&obj->s2, x);
		}
	}
	int x = StackTop(&obj->s2);
	return x;
}

bool myQueueEmpty(MyQueue* obj) {
	if (StackEmpty(&obj->s1) && StackEmpty(&obj->s2))
	{
		return true;
	}
	else
	{
		return false;
	}
}

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

4. 设计循环队列

oj链接

思路分析:

如上所示k是有效数据此时队列满时的两种情况我们可以推出判满的公式就是

(tail+1)%(k+1);

如果tail与head重和队列为空

下面就是我们在进行进队和出队操作时我们要考虑到head和tail会越界因此我们在head与tail加加之后模上(k+1)就不会越界了。

还有就是我们获取队尾元素时按道理是返回下标是tail-1的元素就可以了但如果tail是0呢?如下图这种情况

这时候我们要对下标进行操作((tail-1)+(k+1))%(k+1)就可以了。

#define _CRT_SECURE_NO_WARNINGS
#include<stdbool.h>
#include <stdlib.h>
typedef struct {
	int k;//表示有效数据
	int head;
	int tail;
	int* ans;
} MyCircularQueue;

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
	return obj->head == obj->tail;
}
bool myCircularQueueIsFull(MyCircularQueue* obj) {
	return (obj->tail + 1) % (obj->k + 1) == obj->head;
}
MyCircularQueue* myCircularQueueCreate(int k) {
	//多开一个
	MyCircularQueue* q = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
	if (q == NULL)
	{
		perror("malloc ");
		return NULL;
	}
	q->k = k;
	q->ans = (int*)malloc(sizeof(int) * (k + 1));
	q->head = q->tail = 0;
	return q;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
	if (myCircularQueueIsFull(obj))
	{
		return false;
	}
	else
	{
		obj->ans[obj->tail++] = value;
		obj->tail %= (obj->k + 1);
		return true;
	}
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
	if (myCircularQueueIsEmpty(obj))
	{
		return false;
	}
	else
	{
		obj->head++;
		obj->head %= (obj->k + 1);
		return true;
	}
}

int myCircularQueueFront(MyCircularQueue* obj) {
	if (myCircularQueueIsEmpty(obj))
	{
		return -1;
	}
	else
	{
		return obj->ans[obj->head];
	}
}

int myCircularQueueRear(MyCircularQueue* obj) {
	if (myCircularQueueIsEmpty(obj))
	{
		return -1;
	}
	else
	{
		return obj->ans[((obj->tail-1)+(obj->k+1))%(obj->k+1)];
	}
}




void myCircularQueueFree(MyCircularQueue* obj) {
	free(obj->ans);
	obj->ans = NULL;
	free(obj);
	obj = NULL;
}

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 一本通 OJ 库的测试数据,通常是用来验证提交的代码在各种情况下的正确性。测试数据可以分为两种类型,手动和自动。 手动测试数据是由目的出人根据意和数据范围设计的一组数据,用来检测程序的正确性和运行效率。手动测试数据的优点是能够涵盖各种情况,但缺点是数量相对较少,不足以覆盖所有可能的情况。 自动测试数据是由程序自动生成的一组数据,可以生成大量的数据以检测程序的健壮性和效率。自动测试数据的优点是数量大且可以自动生成,但缺点是可能无法覆盖某些特殊情况,导致漏洞。 对于提交的代码,一本通 OJ 库会对其进行编译和运行,然后与测试数据进行比较,判断代码的正确性和效率。如果代码通过了测试数据,就会被判定为正确,否则会被判定为错误,并给出具体的错误信息,供用户进行调试和改进。 综上所述,一本通 OJ 库的测试数据是一个重要的组成部分,它可以帮助用户测试代码的正确性和运行效率,提高用户的编程技能,同时也可以帮助出人设计更好的目,并保证目的质量和难度。 ### 回答2: 一本通 oj库是一个在线的程序设计竞赛平台,提供了丰富的编程目和测试数据。测试数据是用于对程序进行测评的输入和输出数据集合。在目描述中,会对问进行详细的解释和要求,并提供多组测试数据作为样例,让程序员运行他们的代码,并得到程序的输出结果。 测试数据通常包括正向测试数据和反向测试数据。正向测试数据是指符合目条件的测试数据,覆盖了大多数情况,测试程序是否正确;而反向测试数据则是用于测试程序是否能够正确处理异常情况。 在使用一本通 oj库时,程序员不仅需要通过编写算法和程序的方式解决问,还需要通过分析测试数据来判断自己的代码是否正确。而一本通 oj库的丰富数据集合为程序员提供了充足的测试数据,帮助程序员准确地检测代码中存在的漏洞和错误。 总之,一本通 oj库提供了全面的测试数据来测试程序员的代码是否满足目描述和要求,是程序员进行程序设计竞赛、算法练习和编程学习的良好平台。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值