数据结构——栈和队列OJ

/*代码里所用的函数接口都在上一篇博文。里面只进行说明。*/

1、括号匹配;给定一个只包括 '('')''{''}''['']' 的字符串,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。

  2. 左括号必须以正确的顺序闭合。

注意空字符串可被认为是有效字符串。

函数接口:bool isValid(char* s)

数据结构——栈和队列OJ_第1张图片

//C语言
这道题用栈来操作。复合先进后出。我们把左括号进行压栈,右括号进行对比,匹配上就出栈。
一半布尔值我都是用的 int ,0为假,非0为真。
int bracket(char* bra)
{
	char* p = bra;
	Stack stack;    //定义一个栈
	st_init(&stack);    //初始化栈,下面进行压栈
	while (*p)
	{
		switch (*p)
		{
		case '(':
		case '{':
		case '[':
			st_add(&stack, *p);    //如果是左括号我们都压进栈
			break;
		case ')':
		case '}':
		case ']':
			if (st_empt(&stack))    //如果栈是空的,说明没有左括号,那肯定不匹配
			{
				return 0;
			}
			char left = st_top(&stack);
			if (!((left=='('&&*p == ')')||(left == '{'&&*p == '}')||(left == '['&&*p == ']')))    //这里有个!,是不满足的括号匹配的,我们就返回 0;
			{
				return 0;
			}
			st_del(&stack);    //匹配了,删除栈顶。
		default:
			break;    //遍历完后。退出循环
		}
		++p;
	}
	return 1;    //返回真
}

2、用队列实现栈;使用队列实现栈的下列操作:

  • push(x) -- 元素 x 入栈

  • pop() -- 移除栈顶元素

  • top() -- 获取栈顶元素

  • empty() -- 返回栈是否为空

     栈是先进后出,队列是后进先出。所以实现需要一些手段。下面的图是代码里比较难理解的地方

数据结构——栈和队列OJ_第2张图片

//C语言
typedef struct MyStack
{
	int capacity;
	Queue queue;
}MyStack;    //这个结构体是队列,虽然名字是栈
	//初始化/创建
//	MyStack* stack = (MyStack*)malloc(sizeof(MyStack));//因为没有给内存,则需要在堆上申请内存
MyStack* myst_init(MyStack* stack, int capacity)
{

	assert(stack);//保证传入的stack地址有效
	stack->capacity = capacity;
	qu_init(&(stack->queue));
	return stack;	
}
	//添加
        //栈只能在栈顶进行操作。这儿队尾当作栈顶
void myst_push(MyStack* st, int data)
{
	assert((st->queue.size)<(st->capacity));
	
	qu_push(&(st->queue),data);
}
	//删除
    //删除也要在栈顶,但是队列的删除在队尾。所以需要把队首变成队尾。
void myst_pop(MyStack* st)
{
	assert(st->queue.size>0);
	int size = st->queue.size;
	for (int i = 0; i < size - 1; i++)
	{
		int temp = qu_head(&(st->queue));
		qu_pop(&(st->queue));
		qu_push(&(st->queue), temp);
	}
	qu_pop(&(st->queue));//删除
	--st->queue.size;
}
	//取栈顶元素
void myst_top(MyStack* st)
{
	assert(st->queue.size > 0);
	int size = st->queue.size;
	for (int i = 0; i < size - 1; i++)
	{
		int temp = qu_head(&(st->queue));
		qu_pop(&(st->queue));
		qu_push(&(st->queue), temp);
	}
	int temp2 = qu_head(&(st->queue));
	qu_pop(&(st->queue));
	qu_push(&(st->queue), temp2);
	return temp2;
}
	//判断为空
int myst_empt(MyStack* st)
{
	return qu_empty(&(st->queue));
}

 

取栈顶元素和删除一样的,只是把删除换成了取队首元素的函数而已。  

3、用栈实现队列 

使用栈实现队列的下列操作:

  • push(x) -- 将一个元素放入队列的尾部。

  • pop() -- 从队列首部移除元素。

  • peek() -- 返回队列首部的元素。

  • empty() -- 返回队列是否为空。

有了上面的基础,这个题也就有了一定的思想。中间的删除就看这个图。

数据结构——栈和队列OJ_第3张图片

//C语言
typedef struct MyQueue
{
	int maxSize;
	Stack stackA;    //因为栈只能在栈顶操作,所以我们需要两个栈来实现一个队列
	Stack stackB;
}MyQueue;    //定义一个队列,内部是栈

	//初始化
MyQueue* mtqu_init(MyQueue* queue)
{
	assert(queue);
	queue->maxSize = 0;
	st_init(&(queue->stackA));
	st_init(&(queue->stackB));
	return queue;
}
	//添加
void myqu_push(MyQueue* qu, int data)
{
	st_push(&(qu->stackA), data);//我们在第一个栈进行压栈
}
	//删除
void myqu_pop(MyQueue* qu)    //队列需要先进先出
{
	if (st_empt(&(qu->stackB)))//判断第二个栈是否尾空
	{
		int size = st_size(&(qu->stackA));
		for (int  i = 0; i < size; ++i)
		{
			int temp = st_top(&(qu->stackA));
			st_del(&(qu->stackA));
			st_push(&(qu->stackB), temp);
		}    //我们把第一个栈的元素取出压到第二个栈里面,那么在第一个栈的第一个元素到第
                        //二个栈的栈顶了。我们就可以对栈顶进行删除,这个时候实现对队首的删除。
	}
	st_del(&(qu->stackB));
}
	//返回队首
int myqu_front(MyQueue* qu)
{
	if (st_empt(&(qu->stackB)))
	{
		int size = st_size(&(qu->stackA));
		for (int i = 0; i < size; ++i)
		{
			int temp = st_top(&(qu->stackA));
			st_del(&(qu->stackA));
			st_push(&(qu->stackB), temp);
		}
	}
	return st_top(&(qu->stackB));    //和删除一样,把删除操作换成第二个栈的栈顶元素
}
	//判断为空
int myqu_empty(MyQueue* qu)
{
	return st_empt(&(qu->stackA)) && st_empt(&(qu->stackB));//两个栈为空即空
}

4、实现最小栈

设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。

  • push(x) -- 将元素 x 推入栈中。

  • pop() -- 删除栈顶的元素。

  • top() -- 获取栈顶元素。

  • getMin() -- 检索栈中的最小元素。

    最小栈也需要用两个栈来实现。

数据结构——栈和队列OJ_第4张图片

//C语言
typedef struct MinStack
{
	Stack stack1;
	Stack stack2;
}MinStack;
	//初始化
MinStack* mst_init()
{
	MinStack* stack = (MinStack*)mallloc(sizeof(MinStack));
	assert(stack);
	st_init(&(stack->stack1));
	st_init(&(stack->stack2));
	return stack;
}
	//进栈
void mst_push(MinStack* mst, int data)
{
	st_push(&(mst->stack1),data);
	if (st_empt(&(mst->stack2)))//如果第二个栈为空,直接把这个值压进栈
	{
		st_push(&(mst->stack2), data);
	}
	else        //不是的话就取出第二个栈的栈顶元素,比较两个元素的值
	{
		int min = st_top(&(mst->stack2));
		if (data < min)        //如果所压的元素小于第二个栈的栈顶元素就对第二个栈进行压栈
    //否则就不做任何事情
		{
			min = data;
			st_push(&(mst->stack2), min);
		}
	}
}
	//出栈
void mst_pop(MinStack* mst)
{
	if (st_top(&(mst->stack1)) == st_top(&(mst->stack2)))//如果第一个栈和第二个的栈顶元
        //素相同就把第二个栈顶元素也需要删除,刷新最小值
	{
		st_del(&(mst->stack2));
	}
	st_del(&(mst->stack1));
}
	//获取最小
int mst_min(MinStack* mst)
{
	return st_top(&(mst->stack2));//第二个栈的栈顶元素
}
	//栈顶
int mst_top(MinStack* mst)
{
	return st_top(&(mst->stack1));
}
	//判断为空
int mst_empty(MinStack* mst)
{
	return st_empt(&(mst->stack1));
}

5、设计循环队列

  • MyCircularQueue(k): 构造器,设置队列长度为 k 。

  • Front: 从队首获取元素。如果队列为空,返回 -1 。

  • Rear: 获取队尾元素。如果队列为空,返回 -1 。

  • enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。

  • deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。

  • isEmpty(): 检查循环队列是否为空。

  • isFull(): 检查循环队列是否已满。

   这道题的接口是真滴多。循环队列就是一个员=圆环,然后涉及一个公式。公式解释一下,代码就好理解了,思路也有了。

数据结构——栈和队列OJ_第5张图片

//C语言
//循环队列
	//创建队列
typedef int CQData;
typedef struct CirculateQueue
{
	CQData* arr;
	int size;
	int capacity;
	int front;
	int rear;
}CQ;

CQ* cq_init(int capacity)
{
	CQ* circulateQueue = (CQ*)malloc(sizeof(CQ));
	circulateQueue->arr = NULL;
	circulateQueue->capacity = capacity;
	circulateQueue->front = circulateQueue->rear = circulateQueue->size = 0;
	return circulateQueue;
}
int cq_push(CQ* cq, int data)
{
	if (cq->capacity == cq->size)
	{
		return -1;
	}
	cq->arr[cq->rear] = data;
	cq->rear = (cq->rear + 1) % cq->capacity;
	return data;
}
int cq_pop(CQ* cq)
{
	if (cq->size == 0)
	{
		return -1;
	}
	--cq->size;
	cq->front = (cq->front + 1) % cq->capacity;
	return 1;
}
CQData cq_front(CQ* cq)
{
	if (cq->size == 0)
	{
		return -1;
	}
	return cq->arr[cq->front];
}
CQData cq_rear(CQ* cq)
{
	if (cq->size == 0)
	{
		return -1;
	}
	return cq->arr[(cq->rear + cq->capacity -1) % cq->capacity];
}
int cq_empty(CQ* cq)
{
	return cq->size == 0;
}
int cq_full(CQ* cq)
{
	return cq->size == cq->capacity;
}
void cq_free(CQ* cq)
{
	free(cq->arr);
	free(cq);
}

若文章存在不足,望大家指出,欢迎评论。

你可能感兴趣的:(#,数据结构详解系列)