C语言栈与队列面试题详解

目录
  • 1、括号匹配问题
  • 2、用队列实现栈
  • 3、用栈实现队列
  • 4、设计循环队列

1、括号匹配问题

链接直达:

有效的括号

题目:

思路:

做题前,得先明确解题方案是啥,此题用栈的思想去解决是较为方便的,栈明确指出后进先出。我们可以这样设定:

  • 遇到左括号“ ( ”、“ [ ”、“ { ”,入栈。
  • 遇到右括号“ ) ”、“ ] ”、“ } ”,出栈,跟左括号进行匹配,不匹配就报错。

上两句话的意思就是说我去遍历字符串,如果遇到左括号,就入栈;遇到右括号,就出栈顶元素,并判断这个右括号是否与栈顶括号相匹配,若不匹配则返回false,匹配继续遍历字符串,直到遍历完全,遍历后,检查栈是否为空,若为空,则均匹配,返回true,反之false。

代码如下:

//创建栈结构
typedef char STDataType;
typedef struct Stack
{
	STDataType* a; //存储数据
	int top; //栈顶的位置
	int capacity; //容量
}ST;
//初始化栈
void StackInit(ST* ps);
//销毁栈
void StackDestory(ST* ps);
//压栈
void StackPush(ST* ps, STDataType x);
//出栈
void StackPop(ST* ps);
//判空
bool StackEmpty(ST* ps);
//访问栈顶数据
STDataType StackTop(ST* ps);
//有效元素个数
int StackSize(ST* ps);

//定义:
//初始化栈
void StackInit(ST* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}
//销毁栈
void StackDestory(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->top = 0;
}
//压栈
void StackPush(ST* ps, STDataType x)
{
	assert(ps);
	//如果栈满了,考虑扩容
	if (ps->top == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2; //检测容量
		ps->a = (STDataType*)realloc(ps->a, newcapacity * sizeof(STDataType));
		if (ps->a == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		ps->capacity = newcapacity; //更新容量
	}
	ps->a[ps->top] = x;//将数据压进去
	ps->top++;//栈顶上移
}
//出栈
void StackPop(ST* ps)
{
	assert(ps);
	assert(ps->top > 0);
	ps->top--;
}
//判空
bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0; //如果top为0,那么就为真,即返回
}
//访问栈顶数据
STDataType StackTop(ST* ps)
{
	assert(ps);
	assert(ps->top > 0);
	return ps->a[ps->top - 1]; //top-1的位置才为栈顶的元素
}
//有效元素个数
int StackSize(ST* ps)
{
	assert(ps);
	return ps->top;
}

//创建好了栈开始实现
bool isValid(char* s) {
    ST st;//先创建一个栈
    StackInit(&st);//初始化栈
    while (*s)
    {
        if (*s == '[' || *s == '(' || *s == '{')
        {
            StackPush(&st, *s); //如果是左括号就入栈
            ++s;
        }
        else
        {
            if (StackEmpty(&st))
            {
                return false; //此处说明前面根本没有左括号,导致栈为空,直接返回false
            }
            char top = StackTop(&st); //获取栈顶元素
            StackPop(&st); //出栈顶元素,接下来进行匹配
            if ((*s == ']' && top != '[')
                || (*s == ')' && top != '(')
                || (*s == '}' && top != '{'))
            {
                StackDestory(&st); //返回前先销毁,防止内存泄漏
                return false; //如果不匹配,直接返回false
            }
            else
            {
                //此时匹配,继续比较,直到遍历结束
                ++s;
            }
        }
    }
    //栈为空,说明所有左括号都匹配
    bool ret = StackEmpty(&st);
    StackDestory(&st); //返回前先销毁,防止内存泄漏
    return ret;
}

2、用队列实现栈

链接直达:

用队列实现栈

题目:

思路:

做题之前,再明确下两个基本知识点

  • 栈:后进先出
  • 队列:先进先出

此题要用先进先出的队列来实现后进先出的栈,并模拟实现队列的基本接口。

假设我们有一串数字,进入队列A顺序为1 2 3 4,此时再有一个队列B,此时我们取队列A的队头数据,并将其导入队列B,当队列A出到只剩最后一个时,把队列A给pop删掉,此时队列B就是1 2 3,间接性是实现了栈的功能,实现了后进先出的功能。当我们需要再入数据时,只需往不为空的队列入即可。再出就像刚刚那样。简而言之两句话:

  • 入栈:push数据到不为空的队列。
  • 出栈:把不为空的队列的数据前N-1导入另一个空队列,最后剩下一个删掉。

本质:保持一个队列存储数据,另外一个队列空着,要出栈时,空队列用来导数据。

代码如下:

//创建队列结构
typedef int QDataType; //方便后续更改存储数据类型,本文以int为例
 //创建队列节点
typedef struct QueueNode
{
	QDataType data; //存储数据
	struct QueueNode* next; //记录下一个节点
}QNode;
//保存队头和队尾
typedef struct Queue
{
	QNode* head; //头指针
	QNode* tail; //尾指针
}Queue;
//初始化队列
void QueueInit(Queue* pq);
//销毁队列
void QueueDestory(Queue* pq);
//入队列
void QueuePush(Queue* pq, QDataType x);
//出队列
void QueuePop(Queue* pq);
//判空
bool QueueEmpty(Queue* pq);
//获取有效元素个数
size_t QueueSize(Queue* pq);
//获取队头元素
QDataType QueueFront(Queue* pq);
//获取队尾元素
QDataType QueueBack(Queue* pq);

//定义:
//初始化队列
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->head = pq->tail = NULL;
}
//销毁队列
void QueueDestory(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->head = pq->tail = NULL;
}
//入队列
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	//创建一个新节点保存数据
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	//暴力检测newnode,因为malloc的都要检测
	assert(newnode);
	newnode->next = NULL;
	newnode->data = x;
	//如果一开始没有数据,为空的情况
	if (pq->tail == NULL)
	{
		assert(pq->head == NULL);
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
}
//出队列
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->head && pq->tail); //tail和head均不能为空
	//特殊:当删到head=tail的位置时
	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	//一般情况
	else
	{
		//保存head的下一个节点
		QNode* next = pq->head->next;
		free(pq->head);
		pq->head = next;
	}
}
//判空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->head == NULL;
}
//获取有效元素个数
size_t QueueSize(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	size_t size = 0;
	while (cur)
	{
		size++;
		cur = cur->next;
	}
	return size;
}
//获取队头元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->head); //头部不能为空
	return pq->head->data;
}
//获取队尾元素
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->tail); //尾部不能为空
	return pq->tail->data;
}

/**************创建好队列结构,开始正文模拟实现栈**************/
typedef struct {
	Queue q1; //队列q1
	Queue q2; //队列q2
} MyStack;

MyStack* myStackCreate() {
	MyStack* pst = (MyStack*)malloc(sizeof(MyStack)); //申请一个MyStack类型的栈
	assert(pst);
	QueueInit(&pst->q1);//初始化队列1
	QueueInit(&pst->q2);//初始化队列2
	return pst;
}

void myStackPush(MyStack* obj, int x) {
	assert(obj);
	if (!QueueEmpty(&obj->q1))
	{
		QueuePush(&obj->q1, x);//如果q1不为空,就往q1插入数据
	}
	else
	{
		QueuePush(&obj->q2, x);//这儿不需要知道q2是否为空,直接push
	}
}

int myStackPop(MyStack* obj) {
	assert(obj);
	Queue* emptyQ = &obj->q1; //默认q1为空
	Queue* nonEmtpyQ = &obj->q2;//默认q2不为空
	if (!QueueEmpty(&obj->q1))
	{
		emptyQ = &obj->q2; //若假设错误,则q2为空
		nonEmtpyQ = &obj->q1;//此时q1就为空
	}
	while (QueueSize(nonEmtpyQ) > 1)
	{
		QueuePush(emptyQ, QueueFront(nonEmtpyQ)); //把非空的队列数据导到空的队列,直到只剩一个
		QueuePop(nonEmtpyQ); //此时把非空的队头数据给删掉,方便后续导入数据
	}
	int top = QueueFront(nonEmtpyQ); //记录此时的栈顶数据
	QueuePop(nonEmtpyQ); //删除栈顶数据,使该队列置空
	return top;
}

int myStackTop(MyStack* obj) {
	assert(obj);
	if (!QueueEmpty(&obj->q1))
	{
		return QueueBack(&obj->q1);//如果q1不为空,返回
	}
	else
	{
		return QueueBack(&obj->q2);
	}
}

bool myStackEmpty(MyStack* obj) {
	assert(obj);
	//两个队列均为空,则为空
	return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
}

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

3、用栈实现队列

链接直达:

用栈实现队列

题目:

思路:

假设入栈的顺序为1 2 3 4,那么根据题意,想要达到1 2 3 4的出栈顺序以此实现队列。

此题和上一道题正好相反,用栈实现队列,上一道题中,我们需要把数据来回导,从而实现栈的后进先出功能,但是此题就完全不需要来回导了,只需要导一次即可。

假设我们有两个栈,分别命名为pushST和popST。并往栈pushST里头入4个数据1 2 3 4,在出数据时根据栈的性质只能拿到4,此时我们直接把4拿下来并导入栈popST里头,并继续把pushST栈里的数据导下来,直至栈pushST数据为空。此时popST数据即为  4 3 2 1,刚好反过来了。

根据队列的先进先出规则,进1 2 3 4,出必然是1 2 3 4,而上文已经知晓栈popST的数据为4 3 2 1,当删除数据时,会按照1 2 3 4 的顺序逐个删除。恰好利用栈的性质实现了队列的先进先出功能。并只需导一次即可,无需多次。

代码如下:

//创建栈结构
typedef int STDataType;
typedef struct Stack
{
    STDataType* a; //存储数据
    int top; //栈顶的位置
    int capacity; //容量
}ST;
//初始化栈
void StackInit(ST* ps);
//销毁栈
void StackDestory(ST* ps);
//压栈
void StackPush(ST* ps, STDataType x);
//出栈
void StackPop(ST* ps);
//判空
bool StackEmpty(ST* ps);
//访问栈顶数据
STDataType StackTop(ST* ps);
//有效元素个数
int StackSize(ST* ps);

//初始化栈
void StackInit(ST* ps)
{
    assert(ps);
    ps->a = NULL;
    ps->top = 0;
    ps->capacity = 0;
}
//销毁栈
void StackDestory(ST* ps)
{
    assert(ps);
    free(ps->a);
    ps->a = NULL;
    ps->capacity = ps->top = 0;
}
//压栈
void StackPush(ST* ps, STDataType x)
{
    assert(ps);
    //如果栈满了,考虑扩容
    if (ps->top == ps->capacity)
    {
        int newcapacity = ps->capacity == 0 ? 4 : ps->capacity; //检测容量
        ps->a = (STDataType*)realloc(ps->a, newcapacity * sizeof(STDataType));
        if (ps->a == NULL)
        {
            printf("realloc fail\n");
            exit(-1);
        }
        ps->capacity = newcapacity; //更新容量
    }
    ps->a[ps->top] = x;//将数据压进去
    ps->top++;//栈顶上移
}
//出栈
void StackPop(ST* ps)
{
    assert(ps);
    assert(ps->top > 0);
    ps->top--;
}
//判空
bool StackEmpty(ST* ps)
{
    assert(ps);
    return ps->top == 0; //如果top为0,那么就为真,即返回
}
//访问栈顶数据
STDataType StackTop(ST* ps)
{
    assert(ps);
    assert(ps->top > 0);
    return ps->a[ps->top - 1]; //top-1的位置才为栈顶的元素
}
//有效元素个数
int StackSize(ST* ps)
{
    assert(ps);
    return ps->top;
}

/************创建好栈结构,开始正文************/
typedef struct {
    ST pushST; //插入数据的栈
    ST popST; //删除数据的栈
} MyQueue;

MyQueue* myQueueCreate() {
    MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue)); //申请队列类型
    assert(obj);
    StackInit(&obj->pushST);//初始化pushST
    StackInit(&obj->popST);//初始化popST
    return obj;
}

void myQueuePush(MyQueue* obj, int x) {
    assert(obj);
    StackPush(&obj->pushST, x);//不管有没有数据,都插入
}

int myQueuePop(MyQueue* obj) {
    assert(obj);
    if (StackEmpty(&obj->popST)) //如果popST数据为空,要从pushST里导入数据才能删除
    {
        while (!StackEmpty(&obj->pushST)) //pushST数据不为空,就一直向popST里导入数据
        {
            StackPush(&obj->popST, StackTop(&obj->pushST));//把pushST栈顶数据导到popST里
            StackPop(&obj->pushST);//导完后把pushST栈顶元素删掉,方便后续继续导
        }
    }
    int front = StackTop(&obj->popST); //记录popST栈顶元素
    StackPop(&obj->popST);//删除popST栈顶元素,实现队列先进先出
    return front; //返回栈顶数据
}

//取队头数据
int myQueuePeek(MyQueue* obj) {
    assert(obj);
    //如果popST数据为空,要从pushST里导入数据才能取到队头数据
    if (StackEmpty(&obj->popST))
    {
        while (!StackEmpty(&obj->pushST)) //pushST数据不为空,就一直向popST里导入数据
        {
            StackPush(&obj->popST, StackTop(&obj->pushST));//把pushST栈顶数据导到popST里
            StackPop(&obj->pushST);//导完后把pushST栈顶元素删掉,方便后续继续导
        }
    }
    return StackTop(&obj->popST);//直接返回栈顶元素
}

bool myQueueEmpty(MyQueue* obj) {
    return StackEmpty(&obj->pushST) && StackEmpty(&obj->popST);
}

void myQueueFree(MyQueue* obj) {
    assert(obj);
    StackDestory(&obj->pushST);
    StackDestory(&obj->popST);
    free(obj);
}

4、设计循环队列

链接直达:

设计循环队列

题目:

思路:

此题可以用数组实现,也可以用链表实现,但其实是用数组更加方便些。

数组:

假设队头front和队尾tail都指向第一个数据,在队尾插入数据,tail随着数据的插入跟着移动,tail始终为最后一个数据的下一个位置。删除数据只需要将队头front往后挪即可,不需要按照之前队列的pop一样删完还挪动数据,因为是循环链表,且数据是可以重复利用的。

这样分析下来再加上画图看似没有什么缺陷,但是存在两个问题?

  • 什么情况下数组为空?
  • 什么情况下数组满了?

问题1:

当tail = front时数组为空,看似没什么问题,但相等又要分两种情况。先画个图:

由上图得知,在情况一下,数组里确实是一个数据也没有,并且tail也是等于front的,满足数组为空的条件,但是在情况二下,数组的数据全满,此时的tail和front同样是相等的,这里数组不为空了,而是全满,由此可见,是存在问题的。

解决方案:

这里我们可以多开一个空间,不存放数据,只是用来分别数组为空或满。原理如下:当数组长度为4时,也就是说实际能存放3个有效数据,另外一个空间用来判断空或满,此时判断空或满的条件如下:

  • front == tail 时是空
  • tail 下一个位置是 front 时,就是满

代码如下:

typedef struct {
    int* a; //用数组模拟环形队列
    int front;//队头
    int tail; //队尾
    int k; //表示存的数据长度为k
} MyCircularQueue;

bool myCircularQueueIsFull(MyCircularQueue* obj); //前置声明
bool myCircularQueueIsEmpty(MyCircularQueue* obj);//前置声明

MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));//创建环形链表结构
    assert(obj);
    obj->a = (int*)malloc(sizeof(int) * (k + 1));//多开一个空间,便于后续区分空或满
    obj->front = obj->tail = 0;
    obj->k = k; //队列存储有效数据长度为k
    return obj;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if (myCircularQueueIsFull(obj))
    {
        return false; //队列已满,不能插入数据
    }
    obj->a[obj->tail] = value; //赋值
    if (obj->tail == obj->k)
    {
        obj->tail = 0; //当tail走到尾端
    }
    else
    {
        obj->tail++;
    }
    return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if (myCircularQueueIsEmpty(obj))
    {
        return false; //队列为空,不能删除
    }
    if (obj->front == obj->k)
    {
        obj->front = 0; //当front走到尾端
    }
    else
    {
        obj->front++;
    }
    return true;
}
//取头
int myCircularQueueFront(MyCircularQueue* obj) {
    if (myCircularQueueIsEmpty(obj))
    {
        return -1; //队列为空,取不了
    }
    return obj->a[obj->front]; //返回队头
}
//取尾
int myCircularQueueRear(MyCircularQueue* obj) {
    if (myCircularQueueIsEmpty(obj))
    {
        return -1; //队列为空,取不了
    }
    if (obj->tail == 0)
    {
        return obj->a[obj->k]; //tail为0,队尾在长度的最后一个位置
    }
    else
    {
        return obj->a[obj->tail - 1];
    }
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->front == obj->tail; //front==tail时为空
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    if (obj->tail == obj->k && obj->front == 0)
    {
        return true; //当tail尾端,front在头端时也是满
    }
    else
    {
        return obj->tail + 1 == obj->front; //一般情况,当tail的下一个位置为front时为满
    }
}

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

到此这篇关于C语言栈与队列面试题详解的文章就介绍到这了,更多相关C语言 栈与队列内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言 浅谈栈与队列的定义与操作

    目录 栈的定义 栈的实现 前置 初始化栈 栈的销毁 栈的插入 出栈的操作 取栈顶元素 栈的大小 队列的定义 队列的基本操作 队列的初始化 队列的销毁 队列的插入 队列的删除 队列的判空 取出队头元素 取出队尾元素 队列的大小 栈的定义 栈同样是一种线性表,它的特性是插入元素必须从后面插入,删除元素也是从后面删除,进行数据删除和插入的一端称为栈顶,另一端是栈底. 压栈-就是插入元素 出栈-就是删除元素 它可以用数组实现也可以用链表实现 但是用数组实现更好,因为链表的插入和删除要进行遍历,而数组可以

  • C语言编程数据结构的栈和队列

    目录 栈 数组实现 标题全部代码 Stack_array.c Stack_array.h 初始化数组栈 满栈后扩容 是否为空栈 压栈和退栈 链表实现 stack_chain.h stack_chain.c 整个压栈流程 整个弹栈流程 出栈情况 队列 队列的实现 queue_chain.h queue_chain.c 一个结构体类型用于维护这个队列 概念流程图 入队列的实现 出队列的实现 是否空队 栈 栈是一种以后进先出为顺序对对象进行添加或删除的数据结构 对栈进行形象记忆就像是桌子上的一堆书或一

  • C语言中用栈+队列实现队列中的元素逆置

    下面举例代码: 提到的Q是一个队列,S是一个空栈,实现将队列中的元素逆置的算法 #include<stdio.h> #define MaxSize 10 typedef int ElemType; typedef struct{     ElemType data[MaxSize];     int front,rear; }Queue; typedef struct{     ElemType data[MaxSize];     int top; }SqStack;   void Init

  • C语言循环队列与用队列实现栈问题解析

    目录 “莫听穿林打叶声,何妨吟啸且徐行” 这里是目录 循环队列题目描述题目链接思路分析代码实现 用队列实现栈题目描述题目链接思路分析代码实现 循环队列 循环队列: 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环循环队列的好处:可以重新利用队列的空间.我们可以利用这个队列之前用过的空间.在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间.但是使用循环队列,我们能使用这些空间去存储新的值. 题目描述 设计你

  • C语言用栈模拟实现队列问题详解

    目录 题目描述 题目链接 思路分析 代码实现 题目描述 请你仅使用两个栈实现先入先出队列.队列应当支持一般队列支持的所有操作(push.pop.peek.empty). 你只能使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的. 题目链接 用栈实现队列 思路分析 题目的意思是要用两个栈来模拟实现一个队列.仅可以用栈的基本功能实现队列的基本功能.所以需要创建两个栈.所以这两个栈st1,st2可用一个结构

  • C语言数据结构进阶之栈和队列的实现

    目录 栈的实现: 一.栈的概念和性质 二.栈的实现思路 三.栈的相关变量内存布局图 四.栈的初始化和销毁 五.栈的接口实现: 1.入栈 2.出栈 3.获取栈顶的数据 4.获取栈的元素个数 5.判断栈是否为空 队列的实现: 一.队列的概念和性质 二.队列的实现思路 三.队列相关变量的内存布局图 四.队列的初始化和销毁 五.队列的接口实现: 1. 入数据 2.出数据 3.取队头数据 4.取队尾数据 5.获取队列元素个数 6.判断队列是否为空 总结 栈的实现: 一.栈的概念和性质 栈(stack)又名

  • C语言超详细讲解栈与队列实现实例

    目录 1.思考-1 2.栈基本操作的实现 2.1 初始化栈 2.2 入栈 2.3 出栈 2.4 获取栈顶数据 2.5 获取栈中有效元素个数 2.6 判断栈是否为空 2.7 销毁栈 3.测试 3.1测试 3.2测试结果 4.思考-2 5.队列的基本操作实现 5.1 初始化队列 5.2 队尾入队列 5.3 队头出队列 5.4 队列中有效元素的个数 5.5 判断队列是否为空 5.6 获取队头数据 5.7 获取队尾的数据 5.8 销毁队列 6.测试 6.1测试 6.2 测试结果 1.思考-1 为什么栈用

  • C语言编程数据结构栈与队列的全面讲解示例教程

    目录 一.栈的表示和实现 1栈的概念和结构 2栈的初始化 3压栈(栈顶插入一个数据) 4出栈(栈顶删除一个数据) 5取栈顶元素 6取栈顶元素 7判断栈是否为空 二.队列的表示和实现 1队列的概念及结构 2队列的实现 3队列初始化 4入队(队尾插入一个数据) 5出队(队头删除一个数据) 6取队头数据 7取队尾数据 8计算队列中数据个数 9判断队列是否为空 10销毁队列 总结 一.栈的表示和实现 1栈的概念和结构 栈:一种特殊的线性表(逻辑上数据是连着放的),其只允许在固定的一端进行插入和删除操作.

  • C语言栈与队列面试题详解

    目录 1.括号匹配问题 2.用队列实现栈 3.用栈实现队列 4.设计循环队列 1.括号匹配问题 链接直达: 有效的括号 题目: 思路: 做题前,得先明确解题方案是啥,此题用栈的思想去解决是较为方便的,栈明确指出后进先出.我们可以这样设定: 遇到左括号“ ( ”.“ [ ”.“ { ”,入栈. 遇到右括号“ ) ”.“ ] ”.“ } ”,出栈,跟左括号进行匹配,不匹配就报错. 上两句话的意思就是说我去遍历字符串,如果遇到左括号,就入栈:遇到右括号,就出栈顶元素,并判断这个右括号是否与栈顶括号相匹

  • C语言栈与队列相互实现详解

    目录 一.本章重点 二.队列实现栈 三.栈实现队列 四.解题思路总结 一.本章重点 用两个队列实现栈 用两个栈实现队列 解题思路总结 二.队列实现栈 我们有两个队列: 入栈数据1. 2. 3 可以将数据入队列至队列一或者队列二. 如何出栈? 但出栈要先出1,怎么办? 第一步: 将队列一出队n-1个至队列二. 第二步: pop队列一的最后一个元素. 接下来怎么入栈呢? 将元素入队至不为空的队列. 怎么判断栈空? 队列一和队列二都为空的情况下,栈就是空的. 如何取栈顶元素? 取不为空的队列尾部元素.

  • java 数据结构中栈和队列的实例详解

    java 数据结构中栈和队列的实例详解 栈和队列是两种重要的线性数据结构,都是在一个特定的范围的存储单元中的存储数据.与线性表相比,它们的插入和删除操作收到更多的约束和限定,又被称为限定性的线性表结构.栈是先进后出FILO,队列是先进先出FIFO,但是有的数据结构按照一定的条件排队数据的队列,这时候的队列属于特殊队列,不一定按照上面的原则. 实现栈:采用数组和链表两种方法来实现栈 链表方法: package com.cl.content01; /* * 使用链表来实现栈 */ public cl

  • C语言中指针和数组试题详解分析

    目录 数组题: 程序一(一维数组): 字符数组 程序二(字符数组): 程序三(字符数组): 程序四(字符数组): 程序五(字符数组): 二维数组 程序六( 二维数组): 指针题 程序七( 指针): 程序八( 指针): 程序九( 指针): 程序十( 指针): 程序十( 图): 程序十一( 指针): 程序十二( 指针): 程序十三( 指针): 指针 和 数组 试题解析 小编,在这里想说一下,c语言的最后一节 C预处理,可能还需要一些时间,因为小编,昨天才下载了虚拟机 和 linux 系统,还没开始安

  • C语言 栈与数组的实现详解

    目录 栈的实现 栈的定义 数组实现 静态栈 动态栈 链栈 栈的实现 首先我们思考一个问题,什么是栈? 栈是数据结构的一种,栈在我们日常编码中遇到的非常多,很多人对栈的接触可能仅仅局限在 递归使用的是栈 和 StackOverflowException,栈是一种后进先出的数据结构(可以想象生化金字塔的牢房和生化角斗场的狗洞). 栈的定义 栈(stack)又名堆栈,它是一种运算受限的线性表.限定仅在表尾进行插入和删除操作的线性表.这一端被称为栈顶,相对地,把另一端称为栈底.向一个栈插入新元素又称作进

  • C语言经典指针笔试题详解

    目录 题目一(有关传值调用与非法访问) 题目二 (返回栈空间地址的问题 ) 题目三 (区别传值调用的传址调用) 题目四 (free释放的时机)

  • C语言实现队列的示例详解

    目录 前言 一. 什么是队列 二. 使用什么来实现栈 三. 队列的实现 3.1头文件 3.2 函数的实现 四.完整代码 前言 前一段时间,我们试着用C语言实现了数据结构中的顺序表,单链表,双向循环链表,栈.今天我们再用C语言来实现另一种特殊的线性结构:队列 一. 什么是队列 队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(head)进行删除操作,而在表的后端(tail)进行插入操作,和栈一样,队列是一种操作受限制的线性表.进行插入操作的端称为队尾,进行删除操作的端称为队头. 这个队列就可

  • Java栈和基础队列的实现详解

    目录 栈(stack) 栈支持的三个核心操作: 栈的常见实际应用: 栈的实现 队列 无论是哪种队列,都必须支持三个核心操作: 基础队列的实现 栈和队列:都是线性表,都是基于List基础上的实现 线性表:数组,链表,字符串,栈,队列 元素按照一条“直线”排列,线性表这个结构中,一次添加单个元素 栈(stack) 一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作.进行数据插入和删除操作的一端称为栈顶,另一端称为栈底.栈中的数据元素遵守后进先出LIFO(Last In First Out)

  • C语言sizeof和strlen的指针和数组面试题详解

    目录 一.概念 sizeof: strlen: 二.例题及解析 2.1 一维数组 2.2 字符数组 2.3 二维数组 三.总结 一.概念 sizeof: sizeof操作符的结果类型为size_t,(它在头文件用typedfe定义为unsigned int类型),计算的是分配空间的实际字节数.sizeof是运算符,可以以类型.函数.做参数 . strlen: strlen结果类型也为size_t(size_t strlen( const char *string )),但strlen是计算的空间

  • C语言与C++中内存管理详解

    目录 内存分布 动态内存管理方式-堆区 C语言动态内存管理 C++动态内存管理 new和delete的用法 operator new与operator delete函数 new和delete的实现原理 定位new表达式 高频面试题 重点new/delete和malloc/free的区别 内存泄漏 内存分布 主要段及其分布 ​ 每个程序运行起来以后,它将拥有自己独立的虚拟地址空间.这个虚拟地址空间的大小与操作系统的位数有关系.32位硬件平台的虚拟地址空间的地址可以从0~2^32-1,即0x0000

随机推荐