数据结构--初识栈和队列

1.栈

1.1栈的概念及结构

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶。
在这里插入图片描述

1.2栈的实现

栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更有一些。因为在数组为上插入数据的代价比较小。
在这里插入图片描述
接下来我们一起用数组实现栈

定义结构体

typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;//栈的容量
}ST;

定义一个STDataType类型的指针,int类型的top变量记录位置,int类型的capacity变量记录栈的容量

Stack.h文件

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef int 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);
//判断是否栈空
bool STackEmpty(ST* ps);
//栈的大小
int STackSize(ST* ps);
//获取栈顶元素
STDataType STackTop(ST* ps);

Stack.c文件

#include"Stack.h"
//栈的初始化
void STackInit(ST* ps)
{
	assert(ps);
	STDataType* tmp = (STDataType*)malloc(sizeof(STDataType) * 3);
	if (tmp == NULL)
	{
		perror("STackInit(ST* ps)::malloc");
		return;
	}
	ps->a = tmp;
	ps->capacity = 3;
	ps->top = 0;//指向栈顶元素下一个位置
	//ps->a = -1;//指向栈顶元素的位置
}
//栈的销毁
void STackDestroy(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->capacity = ps->top = 0;
}
//入栈
void STackPush(ST* ps, STDataType x)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		STDataType* tmp = (STDataType*)realloc(ps->a, 
			sizeof(STDataType)*ps->capacity * 2);
		if (tmp == NULL)
		{
			perror("STackPush::realloc");
			return;
		}
		ps->a = tmp;
		ps->capacity *= 2;
	}
	ps->a[ps->top++] = x;
}
//出栈
void STackPop(ST* ps)
{
	assert(ps);
	assert(!STackEmpty(ps));
	ps->top--;
}
//判断是否栈空
bool STackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}
//栈的大小
int STackSize(ST* ps)
{
	assert(ps);
	return ps->top;
}
//获取栈顶元素
STDataType STackTop(ST* ps)
{
	assert(ps);
	assert(!STackEmpty(ps));
	return ps->a[ps->top-1];
}

test.c文件

#include"Stack.h"
int main()
{
	ST st;
	STackInit(&st);
	STackPush(&st, 1);
	STackPush(&st, 2);
	STackPush(&st, 3);
	STackPush(&st, 4);
	STackPush(&st, 5);
	printf("当前栈的大小为:>%d\n", STackSize(&st));
	while (!STackEmpty(&st))
	{
		printf("%d ", STackTop(&st));
		STackPop(&st);
	}
	return 0;
}

代码运行的结果为:
在这里插入图片描述

2.队列

2.1队列的概念及实现

队列:只允许在一端进行插入数据操作,在另一端进行删除操作的特殊线性表,队列具有先进先出(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 QueueNode
{
	struct QueueNode* next;
	QDataType data;
}QNode;
typedef struct Queue
{
	QNode* head;
	QNode* tail;
	int size;
}Queue;
//队列初始化
void QueueInit(Queue* pq);
//队列销毁
void QueueDestroy(Queue* pq);
//入队列
void QueuePush(Queue* pq, QDataType x);
//出队列
void QueuePop(Queue* pq);
//队列大小
int QueueSize(Queue* pq);
//队列判空
bool QueueEmpty(Queue* pq);
//获取队头元素
QDataType QueueFront(Queue* pq);
//获取队尾元素
QDataType QueueBase(Queue* pq);

Queue.c文件

#define _CRT_SECURE_NO_WARNINGS 1
#include"Queue.h"
//队列初始化
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->head = pq->tail = NULL;
	pq->size = 0;
}
//队列销毁
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->head = pq->tail = NULL;
	pq->size = 0;
}
//入队列
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("QueuePush::malloc");
		return;
	}
	newnode->next = NULL;
	newnode->data = x;
	if (pq->head == NULL)
	{
		assert(pq->tail == NULL);
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
	pq->size++;
}
//出队列
void QueuePop(Queue* pq)
{
	assert(pq);
	//QNode* del = pq->head;
	//pq->head = del->next;
	//free(del);
	//if (pq->head == NULL)
	//	pq->tail = NULL;
	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		QNode* next = pq->head->next;
		free(pq->head);
		pq->head = next;
	}
	pq->size--;
}
//队列大小
int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}
//队列判空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->size == 0;
}
//获取队头元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->head->data;
}
//获取队尾元素
QDataType QueueBase(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->tail->data;
}

test.c文件

#define _CRT_SECURE_NO_WARNINGS 1
#include"Queue.h"
int main()
{
	Queue q;
	QueueInit(&q);
	QueuePush(&q, 1);
	QueuePop(&q);
	QueuePush(&q, 2);
	QueuePop(&q);
	QueuePush(&q, 3);
	QueuePush(&q, 4);
	QueuePush(&q, 5);
	printf("队列元素个数为:>%d\n", QueueSize(&q));
	while (!QueueEmpty(&q))
	{
		printf("%d ", QueueFront(&q));
		QueuePop(&q);
	}
	return 0;
}

代码测试的结果为:
在这里插入图片描述

3.栈和队列的面试题

3.1括号匹配问题

在这里插入图片描述
代码实现:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

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);
//判断是否栈空
bool STackEmpty(ST* ps);
//栈的大小
int STackSize(ST* ps);
//获取栈顶元素
STDataType STackTop(ST* ps);
//栈的初始化
void STackInit(ST* ps)
{
	//assert(ps);
	STDataType* tmp = (STDataType*)malloc(sizeof(STDataType) * 3);
	if (tmp == NULL)
	{
		perror("STackInit(ST* ps)::malloc");
		return;
	}
	ps->a = tmp;
	ps->capacity = 3;
	ps->top = 0;//指向栈顶元素下一个位置
	//ps->a = -1;//指向栈顶元素的位置
}
//栈的销毁
void STackDestroy(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->capacity = ps->top = 0;
}
//入栈
void STackPush(ST* ps, STDataType x)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		STDataType* tmp = (STDataType*)realloc(ps->a, 
			sizeof(STDataType)*ps->capacity * 2);
		if (tmp == NULL)
		{
			perror("STackPush::realloc");
			return;
		}
		ps->a = tmp;
		ps->capacity *= 2;
	}
	ps->a[ps->top++] = x;
}
//判断是否栈空
bool STackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}
//出栈
void STackPop(ST* ps)
{
	assert(ps);
	assert(!STackEmpty(ps));
	ps->top--;
}

//栈的大小
int STackSize(ST* ps)
{
	assert(ps);
	return ps->top;
}
//获取栈顶元素
STDataType STackTop(ST* ps)
{
	assert(ps);
	assert(!STackEmpty(ps));
	return ps->a[ps->top-1];
}
 
 bool isValid(char * s)
 {
     ST st;
    STackInit(&st);
    //StackInit(&st);
     while(*s)
     {
         if(*s=='('||*s=='['||*s=='{')
         {
            STackPush(&st,*s);
         }
         else{
             //右括号比左括号多的情况
             if(STackEmpty(&st))
             {
                 STackDestroy(&st);
                 return false;
             }  
             char top=STackTop(&st);
             if((top=='('&&*s!=')')||
             (top=='['&&*s!=']')||
             (top=='{'&&*s!='}'))
             {
                STackDestroy(&st);
                 return false;
             }
             STackPop(&st);
         }
         s++;
     }
     //左括号比右括号多的情况
     bool ret =STackEmpty(&st);
     STackDestroy(&st);
     return ret;
 }

3.2用队列实现栈

在这里插入图片描述
图形理解:
在这里插入图片描述
代码实现:

typedef int QDataType;
typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType data;
}QNode;
typedef struct Queue
{
	QNode* head;
	QNode* tail;
	int size;
}Queue;
//队列初始化
void QueueInit(Queue* pq);
//队列销毁
void QueueDestroy(Queue* pq);
//入队列
void QueuePush(Queue* pq, QDataType x);
//出队列
void QueuePop(Queue* pq);
//队列大小
int QueueSize(Queue* pq);
//队列判空
bool QueueEmpty(Queue* pq);
//获取队头元素
QDataType QueueFront(Queue* pq);
//获取队尾元素
QDataType QueueBase(Queue* pq);

//队列初始化
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->head = pq->tail = NULL;
	pq->size = 0;
}
//队列销毁
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->head = pq->tail = NULL;
	pq->size = 0;
}
//入队列
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("QueuePush::malloc");
		return;
	}
	newnode->next = NULL;
	newnode->data = x;
	if (pq->head == NULL)
	{
		assert(pq->tail == NULL);
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
	pq->size++;
}
//出队列
void QueuePop(Queue* pq)
{
	assert(pq);
	//QNode* del = pq->head;
	//pq->head = del->next;
	//free(del);
	//if (pq->head == NULL)
	//	pq->tail = NULL;
	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		QNode* next = pq->head->next;
		free(pq->head);
		pq->head = next;
	}
	pq->size--;
}
//队列大小
int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}
//队列判空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->size == 0;
}
//获取队头元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->head->data;
}
//获取队尾元素
QDataType QueueBase(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->tail->data;
}
typedef struct {
    Queue q1;
    Queue q2;
} MyStack;


MyStack* myStackCreate() {
    MyStack* pst=(MyStack*)malloc(sizeof(MyStack));
    if(pst==NULL)
    {
        perror("myStackCreate()::malloc");
        return NULL;
    }
    QueueInit(&pst->q1);
    QueueInit(&pst->q2);
    return pst;
}

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

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

int myStackTop(MyStack* obj) {
    if(!QueueEmpty(&obj->q1))
    {
       return QueueBase(&obj->q1);
    }
    else
    {
       return QueueBase(&obj->q2);
    }
}

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

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

3.3用栈实现队列

在这里插入图片描述
图形理解:
在这里插入图片描述
代码实现:

typedef int 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);
//判断是否栈空
bool STackEmpty(ST* ps);
//栈的大小
int STackSize(ST* ps);
//获取栈顶元素
STDataType STackTop(ST* ps);
//栈的初始化
void STackInit(ST* ps)
{
	assert(ps);
	STDataType* tmp = (STDataType*)malloc(sizeof(STDataType) * 3);
	if (tmp == NULL)
	{
		perror("STackInit(ST* ps)::malloc");
		return;
	}
	ps->a = tmp;
	ps->capacity = 3;
	ps->top = 0;//指向栈顶元素下一个位置
	//ps->a = -1;//指向栈顶元素的位置
}
//栈的销毁
void STackDestroy(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->capacity = ps->top = 0;
}
//入栈
void STackPush(ST* ps, STDataType x)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		STDataType* tmp = (STDataType*)realloc(ps->a, 
			sizeof(STDataType)*ps->capacity * 2);
		if (tmp == NULL)
		{
			perror("STackPush::realloc");
			return;
		}
		ps->a = tmp;
		ps->capacity *= 2;
	}
	ps->a[ps->top++] = x;
}
//出栈
void STackPop(ST* ps)
{
	assert(ps);
	assert(!STackEmpty(ps));
	ps->top--;
}
//判断是否栈空
bool STackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}
//栈的大小
int STackSize(ST* ps)
{
	assert(ps);
	return ps->top;
}
//获取栈顶元素
STDataType STackTop(ST* ps)
{
	assert(ps);
	assert(!STackEmpty(ps));
	return ps->a[ps->top-1];
}
typedef struct {
    ST pushst;
    ST popst;
} MyQueue;


MyQueue* myQueueCreate() {
    MyQueue* obj=(MyQueue*)malloc(sizeof(MyQueue));
    if(obj==NULL)
    {
        perror("myQueueCreate()::malloc");
        return NULL;
    }
    STackInit(&obj->pushst);
    STackInit(&obj->popst);
    return obj;
}

void myQueuePush(MyQueue* obj, int x) {
    STackPush(&obj->pushst,x);
}

int myQueuePeek(MyQueue* obj) {
    if(STackEmpty(&obj->popst))
    {
        while(!STackEmpty(&obj->pushst))
        {
            STackPush(&obj->popst,STackTop(&obj->pushst));
            STackPop(&obj->pushst);
        }
    }
    return STackTop(&obj->popst);
}

int myQueuePop(MyQueue* obj) {
    int top=myQueuePeek(obj);
    STackPop(&obj->popst);
    return top;
}


bool myQueueEmpty(MyQueue* obj) {
    return STackEmpty(&obj->pushst)&&
    STackEmpty(&obj->popst);
}

void myQueueFree(MyQueue* obj) {
    STackDestroy(&obj->pushst);
    STackDestroy(&obj->popst);
    free(obj);
}

3.4设计循环队列

在这里插入图片描述
代码实现:

typedef struct {
    int* a;
    int front;//首元素下标
    int rear;//末尾元素的下一个位置
    int k;//循环队列的数据个数
} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    if(obj==NULL)
    {
        perror("myCircularQueueCreate::malloc");
        return NULL;
    }
    int* tmp=(int*)malloc(sizeof(int)*(k+1));//多开一段空间
    if(tmp==NULL)
    {
        perror("myCircularQueueCreate::malloc");
        return NULL;
    }
    obj->a=tmp;
    obj->front=obj->rear=0;
    obj->k=k;
    return obj;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    //rear\front下标相同时,循环队列为空
    return obj->rear==obj->front;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    //rear下一个位置与front的位置相同时,循环队列为满
    return (obj->rear+1)%(obj->k+1)==obj->front;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if(myCircularQueueIsFull(obj))
    {
        return false;
    }
        //obj->a[obj->rear++]=value;
        obj->a[obj->rear++]=value;
        //rear到末尾的情况
        obj->rear %=(obj->k+1);
        return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
    {
        return false;
    }
    obj->front++;
    //front到末尾的情况
    obj->front%=(obj->k+1);
    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;
    }
    else
    {
        //rear前一个的位置为队尾的情况
        //rear在数组开头的时候,特殊处理
        return obj->a[(obj->rear-1+obj->k+1)%(obj->k+1)];
    }
}
void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->a);
    free(obj);
}
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值