数据结构面试例题:括号匹配、栈实现队列、队列实现栈,循坏队列(C语言解决)

hello,这次我来用C语言和栈和队列相关问题,希望大家多多支持


括号匹配题目:

OJ题目

首先我们不能用数量匹配来进行解答,因为你顺序不一定匹配

解析:
1、左括号入栈

2、右括号出栈顶左括号匹配

1.我们只需要找到右括号,判断左括号是否匹配

2、所以遇到左括号就采用进入栈的方式,遇到右括号,出栈顶左括号看是否匹配

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

void StackInit(ST* ps);
void StackDestroy(ST* ps);
void StackPush(ST* ps, STDataType x);
void StackPop(ST* ps);
STDataType StackTop(ST* ps);
int StackSize(ST* ps);
bool StackEmpty(ST* ps);

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


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


void StackPush(ST* ps, STDataType x)
{
	assert(ps);

	if (ps->top == ps->capacity)
	{
		int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		STDataType* tmp = realloc(ps->a, sizeof(STDataType) * newCapacity);
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}

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

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


void StackPop(ST* ps)
{
	assert(ps);
	//assert(ps->top > 0);
	assert(!StackEmpty(ps));

	ps->top--;
}

STDataType StackTop(ST* ps)
{
	assert(ps);
	//assert(ps->top > 0);
	assert(!StackEmpty(ps));

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

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

	return ps->top;
}


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

	return ps->top == 0;
}

bool isValid(char* s) 
{
    ST st;
    StackInit(&st);
    while(*s)
    {
        if (*s == '(' 
        || *s == '{' 
        || *s == '[')
        {
            StackPush(&st, *s);
            ++s;
        }
        else
        {
         
            if (StackEmpty(&st))
            {
                StackDestroy(&st);
                return false;
            }

            STDataType top = StackTop(&st);
            StackPop(&st);
            if ((*s == '}' && top != '{')
            || (*s == ']' && top != '[')
            || (*s == ')' && top != '('))
            {
                StackDestroy(&st);
                return false;
            }
            else
            {
                s++;
            }
        }
    }


    bool ret = StackEmpty(&st);
    StackDestroy(&st);
    return ret;
}

用队列实现栈

OJ题目icon-default.png?t=N7T8https://leetcode.cn/problems/implement-stack-using-queues/description/

我们知道队列是先进先出,栈是先进后出(后入先出)

1、我们主要保证一个队列是空,然后把这个队列数据存入另外一个队列中,这个时候的队列所出的数据相当于就是栈出的数据。

2、所以插入数据是插到有数据的队列,如果两个都没有数据两个都行。 

 

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

/** Initialize your data structure here. */
MyStack* myStackCreate(int maxSize) {
    MyStack* pst = (MyStack*)malloc(sizeof(MyStack));
    QueueInit(&pst->q1);
    QueueInit(&pst->q2);
        
    return pst;
}

/** Push element x onto stack. */
void myStackPush(MyStack* obj, int x) {
    //给非空队列进行入队操作
    if(QueueEmpty(&obj->q1) != 0)
    {
        QueuePush(&obj->q1, x);
    }
    else
    {
        QueuePush(&obj->q2, x);
    }
}

/** Removes the element on top of the stack and returns that element. */
int myStackPop(MyStack* obj) {
    //把非空队列的除最后一个元素之外的剩余元素全部入队空队列
    Queue* pEmpty = &obj->q1, *pNonEmpty = &obj->q2;
    if(QueueEmpty(&obj->q1) != 0)
    {
        pEmpty = &obj->q2;
        pNonEmpty = &obj->q1;
    }
    
    while(QueueSize(pNonEmpty) > 1)
    {
        QueuePush(pEmpty, QueueFront(pNonEmpty));
        QueuePop(pNonEmpty);
    }
    
    int top = QueueFront(pNonEmpty);
    //队尾元素出队
    QueuePop(pNonEmpty);
    
    return top;
}

/** Get the top element. */
int myStackTop(MyStack* obj) {
    //获取非空队列的队尾元素
    Queue* pEmpty = &obj->q1, *pNonEmpty = &obj->q2;
    if(QueueEmpty(&obj->q1) != 0)
    {
        pEmpty = &obj->q2;
        pNonEmpty = &obj->q1;
    }
    
    return QueueBack(pNonEmpty);
}

/** Returns whether the stack is empty. */
bool myStackEmpty(MyStack* obj) {
    return !(QueueEmpty(&obj->q1) | QueueEmpty(&obj->q2));
}

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

用栈实现队列

OJ题目icon-default.png?t=N7T8https://leetcode.cn/problems/implement-queue-using-stacks/description/

typedef struct {
    //入队栈
    Stack pushST;
    //出队栈
    Stack popST;
} MyQueue;

/** Initialize your data structure here. */
MyQueue* myQueueCreate(int maxSize) {
    MyQueue* pqueue = (MyQueue*)malloc(sizeof(MyQueue));
    StackInit(&pqueue->pushST, maxSize);
    StackInit(&pqueue->popST, maxSize);
    return pqueue;
}

/** Push element x to the back of queue. */
void myQueuePush(MyQueue* obj, int x) {
    //入队栈进行入栈操作
    StackPush(&obj->pushST, x);
}

/** Removes the element from in front of queue and returns that element. */
int myQueuePop(MyQueue* obj) {
    //如果出队栈为空,导入入队栈的元素
    if(StackEmpty(&obj->popST) == 0)
    {
        while(StackEmpty(&obj->pushST) != 0)
        {
            StackPush(&obj->popST, StackTop(&obj->pushST));
            StackPop(&obj->pushST);
        }
    }
    
    int front = StackTop(&obj->popST);
    //出队栈进行出队操作
    StackPop(&obj->popST);
    return front;
}

/** Get the front element. */
int myQueuePeek(MyQueue* obj) {
    //类似于出队操作
    if(StackEmpty(&obj->popST) == 0)
    {
        while(StackEmpty(&obj->pushST) != 0)
        {
            StackPush(&obj->popST, StackTop(&obj->pushST));
            StackPop(&obj->pushST);
        }
    }
    
    return StackTop(&obj->popST);
}

/** Returns whether the queue is empty. */
bool myQueueEmpty(MyQueue* obj) {
    return StackEmpty(&obj->pushST) == 0
        &&  StackEmpty(&obj->popST) == 0;
}

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

设计循坏队列

OJ题目icon-default.png?t=N7T8https://leetcode.cn/problems/design-circular-queue/description/

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

/** Initialize your data structure here. Set the size of the queue to be k. */
//创建一个可以存放k个元素的循环队列,实际申请的空间为k + 1
MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* pcq = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    pcq->queue = (int*)malloc(sizeof(int)*(k+1));
    pcq->front = 0;
    pcq->rear = 0;
    pcq->k = k;
    
    return pcq;
}

/** Insert an element into the circular queue. Return true if the operation is successful. */
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    //判满
    if((obj->rear+1)%(obj->k+1) == obj->front)
    {
        return false;
    }
    //队尾入队
    obj->queue[obj->rear++] = value;
    //如果队尾越界,更新为最小值
    if(obj->rear == obj->k+1)
        obj->rear = 0;
    
    return true;
}

/** Delete an element from the circular queue. Return true if the operation is successful. */
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    //判空
    if(obj->front == obj->rear)
        return false;
    //队头出队
    ++obj->front;
    //如果队头越界,更新为最小值
    if(obj->front == obj->k+1)
        obj->front = 0;
    
    return true;
}

/** Get the front item from the queue. */
int myCircularQueueFront(MyCircularQueue* obj) {
    if(obj->front == obj->rear)
        return -1;
    else
        return obj->queue[obj->front];
}

/** Get the last item from the queue. */
int myCircularQueueRear(MyCircularQueue* obj) {
     if(obj->front == obj->rear)
        return -1;
    //队尾元素再rear索引的前一个位置,如果rear为0,
    //则队尾元素在数组的最后一个位置
    if(obj->rear == 0)
        return obj->queue[obj->k];
    else
        return obj->queue[obj->rear-1];
}

/** Checks whether the circular queue is empty or not. */
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->front == obj->rear;
}

/** Checks whether the circular queue is full or not. */
bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return (obj->rear+1)%(obj->k+1) == obj->front;
}

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

一些解析都在代码里啦


希望大家多多支持,更喜欢对你有帮助

  • 82
    点赞
  • 67
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 65
    评论
实验一 进程调度 编写并调试一个模拟的进程调度程序,采用“短进程优先”调度算法对五个进程进行调度。以加深对进程的概念及进程调度算法的理解. 下面是采用动态优先数的调度程序,可作参考。  例题: 设计一个有 N个进程共行的进程调度程序。   进程调度算法:采用最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)和先来先服务算法。   每个进程有一个进程控制块( PCB)表示。进程控制块可以包含如下信息:进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等等。   进程的优先数及需要的运行时间可以事先人为地指定(也可以由随机数产生)。进程的到达时间为进程输入的时间。   进程的运行时间以时间片为单位进行计算。   每个进程的状态可以是就绪 W(Wait)、运行R(Run)、或完成F(Finish)三种状态之一。   就绪进程获得 CPU后都只能运行一个时间片。用已占用CPU时间加1来表示。   如果运行一个时间片后,进程的已占用 CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后把它插入就绪队列等待CPU。   每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的 PCB,以便进行检查。重复以上过程,直到所要进程都完成为止。实验二 作业调度 一、实验目的:用高级语言编写和调试一个或多个作业调度的模拟程序,以加深对作业调度算法的理解。 二、实验内容: 1.写并调试一个单道处理系统的作业等待模拟程序。 2.作业等待算法:分别采用先来先服务(FCFS)、响应比高者优先(HRN)的调度算法。 3.由于在单道批处理系统中,作业一投入运行,它就占有计算机的一切资源直到作业完成为止,因此调度作业时不必考虑它所需要的资源是否得到满足,它所占用的 CPU时限等因素。 4.每个作业由一个作业控制块JCB表示,JCB可以包含如下信息:作业名、提交时间、所需的运行时间、所需的资源、作业状态、链指针等等。作业的状态可以是等待W(Wait)、运行R(Run)和完成F(Finish)三种状态之一。每个作业的最初状态总是等待W。 5.对每种调度算法都要求打印每个作业开始运行时刻、完成时刻、周转时间、带权周转时间,以及这组作业的平均周转时间及带权平均周转时间。 三、思考:比较各种算法的优缺点。 实验三 动态分区分配方式的模拟 1、实验目的:了解动态分区分配方式中的数据结构和分配算法,并进一步加深对动态分区存储管理方式及其实现过程的理解 2、实验内容: (1)用C语言分别实现采用首次适应算法和最佳适应算法的动态分区分配过程和回收过程。其中,空闲分区通过空闲分区链(表)来管理;在进行内存分配时,系统优先使用空闲区低端的空间。 (2)假设初始状态下,可用的内存空间为640KB,并有下列的请求序列: •作业1申请130KB •作业2申请60KB •作业3申请100KB •作业2释放60KB •作业4申请200KB •作业3释放100KB •作业1释放130KB •作业5申请140KB •作业6申请60KB •作业7申请50KB •作业8申请60KB 请分别采用首次适应算法和最佳适应算法进行内存的分配和回收,要求每次分配和回收后显示出空闲内存分区链的情况。 3、思考:讨论各种分配算法的特点。
计算机专业所需,C语言编写,富含例题一、线性表 (一)线性表的定义和基本操作 (二)线性表的实现 1.顺序存储结构 2.链式存储结构 3.线性表的应用 二、队列和数组 (一)队列的基本概念 (二)队列的顺序存储结构 (三)队列的链式存储结构 (四)队列的应用 (五)特殊矩阵的压缩存储 三、树与二叉树 (一)树的概念 (二)二叉树 1.二叉树的定义及其主要特征 2.二叉树的顺序存储结构和链式存储结构 3.二叉树的遍历 4.线索二叉树的基本概念和构造 5.二叉排序树 6.平衡二叉树 (三)树、森林 1.树的存储结构 2.森林与二叉树的转换 3.树和森林的遍历 (四)树的应用 1.等价类问题 2.哈夫曼(Huffman)树和哈夫曼编码 三、图 (一)图的概念 (二)图的存储及基本操作 1.邻接矩阵法 2.邻接表法 (三)图的遍历 1.深度优先搜索 2.广度优先搜索 (四)图的基本应用及其复杂度分析 1.最小(代价)生成树 2.最短路径 3.拓扑排序 4.关键路径 四、查找 (一)查找的基本概念 (二)顺序查找法 (三)折半查找法 (四)B-树 (五)散列(Hash)表及其查找 (六)查找算法的分析及应用 五、内部排序 (一)排序的基本概念 (二)插入排序 1.直接插入排序 2.折半插入排序 (三)气泡排序(bubble sort) (四)简单选择排序 (五)希尔排序(shell sort) (六)快速排序 (七)堆排序 (八)二路归并排序(merge sort) (九)基数排序 (十)各种内部排序算法的比较 (十一)内部排序算法的应用
数据结构是计算机科学中的一个重要概念,它涉及到如何组织和存储数据,以及如何对数据进行操作和处理。C语言是一种常用的编程语言,也是学习数据结构的常用语言之一。下面是一个使用C语言实现数据结构编程例题: 我们考虑一种简单的数据结构——是一种先进后出(LIFO)的数据结构,类似于现实生活中的一叠盘子。我们可以通过数组来实现的基本功能。 首先,我们需要定义一个结构体来表示,该结构体包括一个指向数组的指针,以及一个表示顶位置的整数变量。 ```c typedef struct { int* array; int top; } Stack; ``` 接下来,我们可以定义一些的基本操作,如初始化、判断是否为空、入、出等。 ```c // 初始化 void initStack(Stack* stack, int capacity) { stack->array = (int*)malloc(capacity * sizeof(int)); stack->top = -1; } // 判断是否为空 int isEmpty(Stack* stack) { return stack->top == -1; } // 入 void push(Stack* stack, int element) { stack->array[++stack->top] = element; } // 出 int pop(Stack* stack) { return stack->array[stack->top--]; } ``` 通过上述代码,我们就可以使用C语言实现一个简单的数据结构了。我们可以调用这些函数来进行的初始化、判空、入、出操作。 以上是一个简单的数据结构c语言版编程例题,通过使用C语言实现的基本操作,我们可以更好地理解的原理和实现。当然,数据结构还包括许多其他类型,如链表、队列、树等,对于每种数据结构,我们都可以使用C语言来进行编程实现

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

颦颦Admin@123

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

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

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

打赏作者

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

抵扣说明:

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

余额充值