数据结构_第六关:栈和队列(栈)

Posted 小羊在摸鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构_第六关:栈和队列(栈)相关的知识,希望对你有一定的参考价值。

本关目标:

1.栈

2.队列

3.栈和队列的面试题


目录

1.栈

1.1栈的概念和结构

 1.2关于栈的概念的两个选择题

1.3栈的实现

1)声明

2)实现 

2.栈实现的源代码(vs2022下编译)

3.关于栈的OJ题练习:


1.栈

1.1栈的概念和结构

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

 1.2关于栈的概念的两个选择题

1.一个栈的初始状态为空。现将元素1、2、3、4、5、A、B、C、D、E依次入栈,然后再依次出栈,则元素出栈的顺序是(B)。
A 12345ABCDE
B EDCBA54321
C ABCDE12345
D 54321EDCBA


2.若进栈序列为 1,2,3,4 ,进栈过程中可以出栈,则下列不可能的一个出栈序列是(C)
A 1,4,3,2
B 2,3,4,1
C 3,1,4,2
D 3,4,2,1

栈的出栈顺序不一定非得是数据全部进入完毕后再出,也可以是边进边出。

1.3栈的实现

栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些
因为数组在尾上插入数据的代价比较小。

如果用链表作为栈的话,一般用头做栈顶,尾做栈底,因为链表的头插和头删更有优势

这里我们主要实现数组栈,数组栈分为静态栈和动态栈(和顺序表一样)

静态栈的结构:

typedef int STDataType;
#define N 10
typedef struct Stack

	STDataType _a[N];
	int _top; // 栈顶
Stack;

动态栈结构:

typedef int STDataType;
typedef struct Stack

	STDataType* _a;
	int _top; // 栈顶,初始为0,表示栈顶下一个位置的下标
	int _capacity; // 容量
ST;

下面以动态栈为例,进行实现

1)声明

typedef int STDatatype;
typedef struct Stack

	STDatatype* a;
	int capacity;
	int top;   // 初始为0,表示栈顶位置下一个位置下标
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 StackPrant(ST* ps);

2)实现 

1.初始化

void StackInit(ST* ps)

	assert(ps);

	//可以全部初始化NULL和0
	//ps->a = NULL;
	//ps->top = 0;
	//ps->capacity = 0;

	//也可以先给其开辟4个空间大小的地址
	ps->a = (STDatatype*)malloc(sizeof(STDatatype) * 4);
	if (ps->a == NULL)
	
		perror("malloc fail");
		exit(-1);
	

	ps->top = 0;
	ps->capacity = 4;

如果不在初始化这里开辟大小的话,需要在入栈的realloc前加上:
int NewCapacity = p->capacity == 0 ? 4 : p->capacity * 2;

realloc变为:
STDatatype* tmp = (STDatatype*)realloc(ps->a,  NewCapacity * sizeof(STDatatype));

realloc在pa->a为NULL时会为其开辟新的空间

2.销毁栈

void StackDestroy(ST* ps)

	assert(ps);

	free(ps->a);
	ps->a = NULL;
	ps->top = ps->capacity = 0;

3.入栈

void StackPush(ST* ps, STDatatype x)

	assert(ps);

	// 扩容
	//这里注意top是从0开始的,top指向的是顶的下一个,当存放了4个数据后,top=4(0,1,2,3)
	if (ps->top == ps->capacity)
	
		STDatatype* tmp = (STDatatype*)realloc(ps->a, ps->capacity * 2 * sizeof(STDatatype));
		if (tmp == NULL)
		
			perror("realloc fail");
			exit(-1);
		

		ps->a = tmp;
		ps->capacity *= 2;
	

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

4.出栈

void StackPop(ST* ps)

	//判断栈是不是为NULL
	assert(ps);
	//判断栈里面还有没有元素
	assert(!StackEmpty(ps));

	ps->top--;

5.返回栈顶元素

STDatatype StackTop(ST* ps)

	assert(ps);
	assert(!StackEmpty(ps));

	//栈顶元素是top-1
	return ps->a[ps->top - 1];

 6.返回栈的元素数量

int StackSize(ST* ps)

	assert(ps);

	return ps->top;

因为数据存储是从0开始的,top是栈顶数据+1,刚好就是我们所说的元素数量

7.判断栈是否为空

bool StackEmpty(ST* ps)

	assert(ps);

	/*if (ps->top == 0)
	
		return true;
	
	else
	
		return false;
	*/

	return ps->top == 0;

8.打印栈

void StackPrant(ST* ps)

	int i = 0;
	while (i != ps->top)
	
		printf("%d ", ps->a[i]);
		i++;
	
	printf("\\n");

2.栈实现的源代码(vs2022下编译)

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



//声明

typedef int STDatatype;
typedef struct Stack

	STDatatype* a;
	int capacity;
	int top;   // 初始为0,表示栈顶位置下一个位置下标
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 StackPrant(ST* ps);



//实现

void StackInit(ST* ps)

	assert(ps);

	//可以全部初始化NULL和0
	//ps->a = NULL;
	//ps->top = 0;
	//ps->capacity = 0;

	//也可以先给其开辟4个空间大小的地址
	ps->a = (STDatatype*)malloc(sizeof(STDatatype) * 4);
	if (ps->a == NULL)
	
		perror("malloc fail");
		exit(-1);
	

	ps->top = 0;
	ps->capacity = 4;


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);

	// 扩容
	//这里注意top是从0开始的,top指向的是顶的下一个,当存放了4个数据后,top=4(0,1,2,3)
	if (ps->top == ps->capacity)
	
		STDatatype* tmp = (STDatatype*)realloc(ps->a, ps->capacity * 2 * sizeof(STDatatype));
		/*if (tmp == NULL)
		
			perror("realloc fail");
			exit(-1);
		*/

		ps->a = tmp;
		ps->capacity *= 2;
	

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


void StackPop(ST* ps)

	//判断栈是不是为NULL
	assert(ps);
	//判断栈里面还有没有元素
	assert(!StackEmpty(ps));

	ps->top--;


STDatatype StackTop(ST* ps)

	assert(ps);
	assert(!StackEmpty(ps));

	//栈顶元素是top-1
	return ps->a[ps->top - 1];


int StackSize(ST* ps)

	assert(ps);

	return ps->top;


bool StackEmpty(ST* ps)

	assert(ps);

	/*if (ps->top == 0)
	
		return true;
	
	else
	
		return false;
	*/

	return ps->top == 0;


void StackPrant(ST* ps)

	int i = 0;
	while (i != ps->top)
	
		printf("%d ", ps->a[i]);
		i++;
	
	printf("\\n");




//测试

void text1()

	ST ps;
	StackInit(&ps);
	StackPush(&ps, 1);
	StackPush(&ps, 2);
	StackPush(&ps, 3);
	StackPush(&ps, 4);
	StackPush(&ps, 5);
	StackPush(&ps, 6);
	StackPush(&ps, 7);
	StackPush(&ps, 8);

	StackPrant(&ps);
	int a = StackTop(&ps);
	printf("size:%d,栈顶元素为:%d\\n", StackSize(&ps),a); // 不关心底层实现,直接用

    printf("size:%d\\n", ps.top);  // 关心底层实现

	StackPop(&ps);
	StackPop(&ps);
	StackPop(&ps);

	StackPrant(&ps);
	a = StackTop(&ps);
	printf("size:%d,栈顶元素为:%d\\n", StackSize(&ps), a);





int main()

	text1();
	return 0;

3.关于栈的OJ题练习:

有效的括号

 思路:

  • 利用栈进行判断,首先我们创建一个新的栈
  • 在遇到左括号的时候,放入栈里面
  • 在遇到右括号的时候,出栈,并拿出栈的元素与其进行判断
  • 如果有不相同的情况直接return false
  • 注意特殊情况的处理:
    1:如果,最后栈里面还剩左括号的元素,栈不为空,不符合要求,返回false
    2:如果数组中只有右括号,在进行比较的时候,由于我们的栈里面没有元素,肯定会报错
          所以需要在之前就进行一次判断,判断我们的栈是否为空,为空返回false就行

代码:

主要实现的函数:

bool isValid(char * s)

    //创建一个新的栈
    ST st;
    StackInit(&st);
    //如果*s为空退出循环
    while(*s)
    
        if(*s=='[' || *s=='(' || *s=='')
        
            StackPush(&st,*s);
            ++s;
        
        else
        
            //如果数组中只有右括号,直接对栈进行判空操作
            if(StackEmpty(&st))
            
                StackDestroy(&st);
                return false;
            
            
            char 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;

全部代码:

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

typedef char STDatatype;
typedef struct Stack

	STDatatype* a;
	int capacity;
	int top;   // 初始为0,表示栈顶位置下一个位置下标
ST;

//初始化
void StackInit(ST* ps);

//销毁
void StackDestroy(ST* ps);

//入栈
void StackPush(ST* ps, STDatatype x);

//出栈
void StackPop(ST* ps);

//获取栈顶元素
STDatatype StackTop(ST* ps);

//判断栈是否为空
bool StackEmpty(ST* ps);

void StackInit(ST* ps)

	assert(ps);

	ps->a = (STDatatype*)malloc(sizeof(STDatatype) * 4);
	if (ps->a == NULL)
	
		perror("malloc fail");
		exit(-1);
	

	ps->top = 0;
	ps->capacity = 4;


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)
	
		STDatatype* tmp = (STDatatype*)realloc(ps->a, ps->capacity * 2 * sizeof(STDatatype));

		ps->a = tmp;
		ps->capacity *= 2;
	

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


void StackPop(ST* ps)

	//判断栈是不是为NULL
	assert(ps);
	//判断栈里面还有没有元素
	assert(!StackEmpty(ps));

	ps->top--;


STDatatype StackTop(ST* ps)

	assert(ps);
	assert(!StackEmpty(ps));

	//栈顶元素是top-1
	return ps->a[ps->top - 1];


bool StackEmpty(ST* ps)

	assert(ps);

	return ps->top == 0;


bool isValid(char * s)

    //创建一个新的栈
    ST st;
    StackInit(&st);
    //如果*s为空退出循环
    while(*s)
    
        if(*s=='[' || *s=='(' || *s=='')
        
            StackPush(&st,*s);
            ++s;
        
        else
        
            //如果数组中只有右括号,直接对栈进行判空操作
            if(StackEmpty(&st))
            
                StackDestroy(&st);
                return false;
            
            
            char 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;

数据结构- 栈和队列的实现

文章目录

采用数组实现

#include<iostream>
typedef int DataType;
using namespace std;
typedef struct Stack
{
	DataType* _array;
	int _top;// 表示有效元素个数 表示栈顶位置
	int _capcity;//栈容量
}Stack;

void StackInit(Stack* s)
{
	s->_array = (DataType*)malloc(sizeof(DataType));
	s->_top = 0;
	s->_capcity = 1;
}

void StackDestory(Stack* s)
{
	if (s->_array)
	{
		free(s->_array);
		s->_array = NULL;
		s->_top = 0;
		s->_capcity = 0;
	}
}

void StackPush(Stack* p, DataType data)
{
	//如果栈顶大于等于容量则扩容
	if (p->_top >= p->_capcity)
	{
		p->_array = (DataType*)realloc(p->_array, sizeof(DataType)*(2 * p->_capcity));
		p->_capcity *= 2;
	}
	p->_array[p->_top++] = data;
}

void StackPop(Stack* s)
{
	if (s->_top < 0)return;
	s->_top--;
}

DataType StackTop(Stack* s)
{
	return s->_array[s->_top - 1];
}

int StackEmpty(Stack* s)
{
	return s->_top == 0 ? 1 : 0;
}

int StackSize(Stack* s)
{
	return s->_top;
}

int main()
{
	
}


队列

队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头

采用链表实现

#include<iostream>
typedef int DataType;
using namespace std;
typedef struct Node
{
	DataType _data;
	struct Node* next;
}Node,*pNode;
typedef struct Queue
{
	pNode pHead;//队头
	pNode pTail;//队尾
};

pNode CreateNode(DataType data)
{
	pNode pNewNode = (pNode)malloc(sizeof(pNode));
	pNewNode->_data = data;
	pNewNode->next = nullptr;
	return pNewNode;
}

void QueueInit(Queue* q)
{
	q->pHead = nullptr;
	q->pTail = nullptr;
}

void QueuePush(Queue* q, DataType data)
{
	if (q->pHead == NULL)
	{
		q->pHead = q->pTail = CreateNode(data);
	}
	else
	{
		q->pTail->next = CreateNode(data);
		q->pTail = q->pTail->next;
	}
}

void QueuePop(Queue* q)
{
	pNode t = q->pHead;
	if (t != nullptr)
	{
		q->pHead = t->next;
		free(t);
	}

}

DataType QueueFront(Queue* q)
{
	return q->pHead->_data;
}

DataType QueueBack(Queue* q)
{
	return q->pTail->_data;
}

int QueueSize(Queue* q)
{
	int count = 0;
	pNode t = q->pHead;
	while (t != nullptr)
	{
		count++;
		t = t->next;
	}
	return count;
}
int QueueEmpty(Queue* q)
{
	return q->pHead == nullptr;
}

以上是关于数据结构_第六关:栈和队列(栈)的主要内容,如果未能解决你的问题,请参考以下文章

3.1_栈和队列_栈

数据结构- 栈和队列的实现

数据结构- 栈和队列的实现

数据结构- 栈和队列的实现

剑指Offer数据结构之栈和队列[Python版]

剑指Offer数据结构之栈和队列[Python版]