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

本关目标:

1.栈

2.队列

3.栈和队列的面试题


目录

1.栈

1.1栈的概念和结构

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

1.3栈的实现

1)声明

2)实现 

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

3.关于栈的OJ题练习:


1.栈

1.1栈的概念和结构

数据结构_第六关:栈和队列(栈)_第1张图片

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

数据结构_第六关:栈和队列(栈)_第2张图片

 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栈的实现

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

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

数据结构_第六关:栈和队列(栈)_第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 
#include 
#include 
#include 



//声明

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题练习:

有效的括号

数据结构_第六关:栈和队列(栈)_第4张图片

 思路:

  • 利用栈进行判断,首先我们创建一个新的栈
  • 在遇到左括号的时候,放入栈里面
  • 在遇到右括号的时候,出栈,并拿出栈的元素与其进行判断
  • 如果有不相同的情况直接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 
#include 
#include 
#include 

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

你可能感兴趣的:(初阶数据结构,数据结构)