当前位置: 首页> 财经> 金融 > 设计师服务平台鱼巴士官网_unity游戏制作软件_重庆seo网页优化_昆明网络推广优化

设计师服务平台鱼巴士官网_unity游戏制作软件_重庆seo网页优化_昆明网络推广优化

时间:2025/7/9 3:17:48来源:https://blog.csdn.net/2301_81348661/article/details/144314415 浏览次数:1次
设计师服务平台鱼巴士官网_unity游戏制作软件_重庆seo网页优化_昆明网络推广优化

目录

1.栈

1.1.栈的概念及结构

1.2.栈的实现

2.队列

2.1.队列的概念及结构

2.2.队列的实现

3.运用栈理解一道题

4.使用两个队列实现一个栈


1.栈

1.1.栈的概念及结构

首先,我们来了解一种新的数据结构——栈。栈是一种特殊的线性表,其只允许在固定一端进行插入和删除元素操作。进行数据的插入和删除这一端,称之为栈顶,另一端即栈底。栈中的数据是采取后进先出 LIFOLast In First Out的规则。这里有一些更为专业的话术: 

压栈:栈的插入操作(也称为进栈/压栈) 

出栈:栈的删除操作                                                        

栈的导入与导出数据均在栈顶进行。值得注意的是:栈的导出不一定是根据栈的导入时的顺序进行的。

1.2.栈的实现

我们可以使用数组或链表来实现栈,对数组而言,在数组尾部插入数据代价较小,因为其不需要遍历整个数组。下图演示栈的后进先出。

接下来,我们分析栈的实现

Stack.h 

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>typedef int STDataType;
typedef struct Stack {STDataType* a;int top;//栈的个数int capacity;//容量:扩容
}ST;//初始化
void STInit(ST* pst);
//销毁
void STDestory(ST* pst);
//入栈
void STPush(ST* pst, STDataType x);
//出栈
void STPop(ST* pst);
//取出栈的数据
STDataType STTop(ST* pst)
//判空
bool STEmpty(ST* pst);
//获取数据个数
STDataType STSize(ST* pst);

Stack.c

STInit: 对栈进行初始化,该栈使用数组实现,a(数组名),top(指向栈顶位置的下一个位置),capacity(容量)。 

#include"stack.h"
void STInit(ST* pst) {assert(pst);pst->a = NULL;//top指向栈顶数据的下一个位置pst->top = 0;pst->capacity = 0;
}

STPush:将数据导入栈中,首先,将空间进行扩容(防止空间不足引起的越界访问),并将扩容后的空间传给数组a,然后,再于新空间进行导入数据的操作,结尾记得改变新栈的个数。 

//入栈
void STPush(ST* pst, STDataType x) {assert(pst);if (pst->top == pst->capacity) {//扩容int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;STDataType* tmp = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));if (tmp == NULL) {perror("Realloc failed\n");exit(1);}//将扩容后的地址(指针)传递给 pst->apst->a = tmp;//更新扩容后,容器的大小pst->capacity = newcapacity;}//将 x 插入栈中pst->a[pst->top] = x;pst->top++;
}

STPop:导出栈中的数据,直接传数组的实参,将其栈的个数减少一位,便导出一个数据。

//出栈
void STPop(ST* pst) {assert(pst);assert(pst->top > 0);pst->top--;
}

STTop:由于top指向栈顶的下一个位置,使用我们解引用top-1位置,也就是栈顶数据。

//取出栈的数据
STDataType STTop(ST* pst) {assert(pst);assert(pst->top > 0);return pst->a[pst->top - 1];
}

STEmpty: 通过return返回值(bool型)

//判空
bool STEmpty(ST* pst) {assert(pst);return pst->top == 0;
}

STSize:top指向栈顶的下一个位置,对应数组的数据个数=下标+1,top即栈的数据个数。 

//获取数据个数
STDataType STSize(ST* pst) {assert(pst);return pst->top;
}

STDestroy: 将栈内的数据置空或变为0。

//销毁
void STDestroy(ST* pst) {assert(pst);free(pst->a);pst->a = NULL;pst->top = pst->capacity = 0;
}

 以上便是栈的实现全部过程。


2.队列

2.1.队列的概念及结构

队列与栈不同的是,队列是一种只允许一端进行插入数据,另一端进行删除数据的特殊线性表。队列采取的是先进先出 FIFO(First In First Out) 入队列,在队尾上进行插入数据操作,在队头进行删除数据操作。

2.2.队列的实现

接下来,我们使用具体的代码进行队列的实现。

queue.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>typedef int QDataType;// 链式结构:表示队列 
typedef struct QListNode
{struct QListNode* next;QDataType val;
}QNode;// 队列的结构 
typedef struct Queue
{QNode* qhead;QNode* qtail;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);

queue.c

QueueInit: 首先,我们使用了一个Queue的结构体,声明了qhead和qtail两个链表,现在,我们将其进行初始化。

// 初始化队列 
void QueueInit(Queue* q)
{assert(q);q->qhead = NULL;q->qtail = NULL;q->size = 0;
}

QueuePush:我们可以先开辟链式结构的空间,如果qtail尾有节点,即:先将其next节点的值改为newnode,再将qtail节点与newnode节点相互连接。

// 队尾入队列 
void QueuePush(Queue* q, QDataType data)
{assert(q);QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL) {perror("malloc failed\n");exit(1);}newnode->next = NULL;newnode->val = data;if(q->qtail == NULL){q->qhead = q->qtail = newnode;}else{q->qtail->next = newnode;q->qtail = newnode;}q->size++;
}

QueuePop:如果队列只有一个节点即队头,那我们直接将其free,并置为空;若节点大于一个,那我们可以创建一个QNode*的next节点指向队头指向的下一个节点,然后再将队头的节点free,再重新将队头的节点改为next指针指向的新节点。 

// 队头出队列 
void QueuePop(Queue* q) 
{assert(q);assert(q->size!=0);if (q->qhead->next == NULL) {free(q->qhead);q->qhead = q->qtail = NULL;}else {QNode* next = q->qhead->next;free(q->qhead);q->qhead = next;}q->size--;
}

以下,获取队头元素、队尾元素、队列中有效元素个数 、判空函数均于栈的实现思想大体一致,在这里就不赘述了。

// 获取队列头部元素 
QDataType QueueFront(Queue* q) 
{assert(q);assert(q->qhead);return q->qhead->val;
}
// 获取队列队尾元素 
QDataType QueueBack(Queue* q)
{assert(q);assert(q->qtail);return q->qtail->val;
}
// 获取队列中有效元素个数 
int QueueSize(Queue* q)
{assert(q);return q->size;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q)
{assert(q);return q->size == 0;
}

QueueDestroy:销毁队列,我们可以采取遍历整个队列的方式,将其中的数据从头至尾进行free。 

// 销毁队列 
void QueueDestroy(Queue* q)
{assert(q);QNode* cur = q->qhead;while (cur){QNode* next = cur->next;free(cur);cur = next;}q->qhead = q->qtail = NULL;q->size = 0;
}

3.运用栈理解一道题

首先,我们已经实现好了栈,接下来,我们可以直接使用栈的函数

对于这道题,我们应该先开辟一个栈(st),我们可以先将题目给定(s)的 '('  、'['  、 '{' 这三个左括号导入栈(st)中。 然后,我们可以使用STTop取出栈(st)中的数据,进行对栈(s)的左右括号的匹配,如果匹配不成功,则返回false,直到栈(s)为空时,过程结束。代码如下所示:

bool isValid(char* s) 
{   ST st;STInit(&st);while(*s){if(*s =='(' || *s == '[' || *s == '{'){STPush(&st,*s);  //入栈:让字符串s的括号进入栈st中}else{if(STEmpty(&st)){STDestory(&st);return false;}char top = STTop(&st);//STtop为取栈中数据的函数STPop(&st);//pst->top--;//检验不匹配if((top == '(' && *s != ')')||(top == '[' && *s != ']')||(top == '{' && *s != '}')){STDestory(&st);return false;}}++s;}bool ret = STEmpty(&st);STDestory(&st);return ret;
}

4.使用两个队列实现一个栈

为了加深栈和队列的理解,我们来分析这道题

依照题意,我们创建一个栈(MyStack),包含两个队列(Queue q1\q2) ;

然后,我们需要为新创建的栈开辟新的空间(obj),并将其中的两个队列q1、q2初始化;

设计一个函数myStackPush,用于非空队列尾部添加数据;

在函数myStackPop中,我们将非空队列的size-1个元素移动至空队列中;

然后,使用mytStackTop函数取得栈顶元素;

为了检测我们实现的栈是否为空,我们可以直接使用QueueEmpty返回这两个队列q1、q2;

最后,当我们释放内存的时候,我们应先将这两个队列q1、q2先释放,最后再释放obj这个指向栈(MyStack)的指针。

大致结构如下图所示:

       代码实现见下图分析:

typedef struct {Queue q1;Queue q2;//新创建的栈有两个队列q1,q2
} MyStack;//创建新的栈
MyStack* myStackCreate() {MyStack* obj = (MyStack*)malloc(sizeof(MyStack));QueueInit(&(obj->q1));QueueInit(&(obj->q2));return obj; 
}//在非空队列尾部添加数据x
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* nonEmpty = &(obj->q2);if(!QueueEmpty(&(obj->q1))){nonEmpty = &(obj->q1);empty = &(obj->q2);}while(QueueSize(nonEmpty)>1)//把前size-1个元素导走{QueuePush(empty,QueueFront(nonEmpty));//将有非空队列的队列头部元素 导入 空队列中QueuePop(nonEmpty);//然后,删除非空队列的头部元素}int top = QueueFront(nonEmpty);//再取出非空队列的队头元素QueuePop(nonEmpty);//将非空元素的最后一个队头导出队列return top;//此时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));//boolean empty() 如果栈是空的,返回 true ;否则,返回 false
}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);
*/

 

关键字:设计师服务平台鱼巴士官网_unity游戏制作软件_重庆seo网页优化_昆明网络推广优化

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: