四战数据结构--栈

栈是什么呢?下个定义:栈是一种特殊的线性表

进行数据插入和删除操作的一端 称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出(Last In First Out)的原则。

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。

出栈:栈的删除操作叫做出栈。出数据也在栈顶。

栈的具体实现有两种选择:用顺序表(顺序栈)或者链表(链栈)。相对链表而言,顺序表的结构实现更优一些:数组在尾上插入数据的代价比较小。

顺序栈

声明
typedef int STDataType;
typedef struct Stack
{
	int* a;
	int top;        //栈顶
	int capacity;   //容量
}ST;
初始化栈

此时需要明确top的含义,是指向栈顶元素还是指向栈顶元素的下一个元素,若指向栈顶元素,则初始化不开辟空间时应把top置为-1,若指向栈顶元素的下一个元素,则将top初始化为0。此处以top指向栈顶元素的下一个元素为例:

void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->capacity = 0;
	pst->top =0;    //指向栈顶元素的下一个元素
	//pst->top = -1;  //指向栈顶元素
}
入栈
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, sizeof(STDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
		}
		pst->a = tmp;
		pst->capacity = newcapacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}
出栈
void STPop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);
	pst->top--;
}
获取栈顶元素
STDataType STTop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);
	return pst->a[pst->top - 1];
}
判断栈空
bool STEmpty(ST* pst)
{
	assert(pst);
	return pst->top == 0;
}
栈中有效元素个数
int STSize(ST* pst)
{
	assert(pst);
	return pst->top;
}
销毁栈
void STDestroy(ST* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->top = pst->capacity = 0;
}

完整代码(顺序栈)

Stack.h

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int STDataType;
typedef struct Stack
{
	int* a;
	int top;        //栈顶
	int capacity;   //容量
}ST;
void STInit(ST* pst);
void STDestroy(ST* pst);
void STPush(ST* pst,STDataType x);
void STPop(ST* pst);
STDataType STTop(ST* pst);
bool STEmpty(ST* pst);
int STSize(ST* pst);

Stack.c

#include"Stack.h"
void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->capacity = 0;
	pst->top =0;    //指向栈顶元素的下一个元素
	//pst->top = -1;  //指向栈顶元素
}
void STDestroy(ST* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->top = pst->capacity = 0;
}
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, sizeof(STDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
		}
		pst->a = tmp;
		pst->capacity = newcapacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}
void STPop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);
	pst->top--;
}
STDataType STTop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);
	return pst->a[pst->top - 1];
}
bool STEmpty(ST* pst)
{
	assert(pst);
	return pst->top == 0;
}
int STSize(ST* pst)
{
	assert(pst);
	return pst->top;
}

test.c

#include"Stack.h"
int main()
{
	ST s;
	STInit(&s);
	STPush(&s, 1);
	STPush(&s, 2);
	STPush(&s, 3);
	STPush(&s, 4);
	STPush(&s, 5);
	printf("%d\n", STSize(&s));
	while (!STEmpty(&s))
	{
		printf("%d ", STTop(&s));
		STPop(&s);
	}
	//一种入栈顺序对应多种出栈顺序
	printf("\n%d\n", STSize(&s));
	STDestroy(&s);
	return 0;
}

链栈

声明

typedef int STDataType;
typedef struct Stack
{
    STDataType data;
	struct Stack* next;
}ST;

初始化栈

基于单向不循环带头链表实现,链表首元素为有效元素个数

ST* initStack()
{
	ST* s = (ST*)malloc(sizeof(ST));
	s->data = 0;
	s->next = NULL;
	return s;
}

入栈

void push(ST* s, int data)
{
	ST* st = (ST*)malloc(sizeof(ST));
	st->data = data;
	st->next = s->next;
	s->next = st;
	s->data++;
}

出栈

STDataType pop(ST* s)
{
	if (isempty(s))
	{
		return -1;
	}
	else
	{
		ST* st = s->next;
		STDataType data = st->data;
		s->next = st->next;
		free(st);
		st = NULL;
        s->data--;
		return data;
	}
}

栈中有效元素个数

STDataType gettop(ST* s)
{
	if (isempty(s))
	{
		return -1;
	}
	else
	{
		return s->data;
	}
}

判断栈空

bool isempty(ST* s)
{
	if (s->data == 0 || s->next == NULL)
	{
		return true;
	}
	else
	{
		return false;
	}
}

打印链栈

void printstack(ST* s)
{
	ST* st = s->next;
	while (st)
	{
		printf("%d->", st->data);
		st = st->next;
	}
	printf("NULL\n");
}

销毁栈

void destroyStack(ST* s)
{
	if (isempty(s))
	{
		return;
	}
	else
	{
		ST* st = s->next;
		while (s&&st)
		{
			free(s);
			s = st;
			st = st->next;
		}
		free(s);
		s = NULL;
		return;
	}
}

 完整代码(链栈)

Stack.h

#pragma once
#include<stdbool.h>
#include<stdio.h>
#include<stdlib.h>
typedef int STDataType;
typedef struct Stack
{
    STDataType data;
	struct Stack* next;
}ST;
ST* initStack();
bool isempty(ST* s);
STDataType gettop(ST* s);
STDataType pop(ST* s);
void push(ST* s, int data);
void printstack(ST* s);
void destroyStack(ST* s);

Stack.c

#include"Stack.h"
ST* initStack()
{
	ST* s = (ST*)malloc(sizeof(ST));
	s->data = 0;
	s->next = NULL;
	return s;
}
bool isempty(ST* s)
{
	if (s->data == 0 || s->next == NULL)
	{
		return true;
	}
	else
	{
		return false;
	}
}
STDataType gettop(ST* s)
{
	if (isempty(s))
	{
		return -1;
	}
	else
	{
		return s->data;
	}
}
STDataType pop(ST* s)
{
	if (isempty(s))
	{
		return -1;
	}
	else
	{
		ST* st = s->next;
		STDataType data = st->data;
		s->next = st->next;
		free(st);
		st = NULL;
		s->data--;
		return data;
	}
}
void push(ST* s, int data)
{
	ST* st = (ST*)malloc(sizeof(ST));
	st->data = data;
	st->next = s->next;
	s->next = st;
	s->data++;
}
void printstack(ST* s)
{
	ST* st = s->next;
	while (st)
	{
		printf("%d->", st->data);
		st = st->next;
	}
	printf("NULL\n");
}
void destroyStack(ST* s)
{
	if (isempty(s))
	{
		return;
	}
	else
	{
		ST* st = s->next;
		while (s&&st)
		{
			free(s);
			s = st;
			st = st->next;
		}
		free(s);
		s = NULL;
		return;
	}
}

test.c

#include"Stack.h"
int main()
{
	ST* s = initStack();
	push(s, 1);
	push(s, 2);
	push(s, 3);
	push(s, 4);
	printstack(s);
	pop(s);
	pop(s);
	printstack(s);
	if (isempty(s)==0)
	{
		printf("%d ", gettop(s));
	}
	destroyStack(s);
	return 0;
}

 练习题 

看到这道题,大家可能第一想法是计算左右括号个数是否相等,但是题意不仅要我们满足数量匹配,还要满足顺序匹配,所以此路不通。那这题怎么解决呢?答案就是:用刚学的栈!

思路:

1.遇到左括号入栈

2.遇到有括号将栈顶左括号出栈看是否匹配

代码(真的很需要一个库,不想当小丑了):

typedef char STDataType;
typedef struct Stack
{
	char* a;
	int top;        
	int capacity;   
}ST;
void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->capacity = 0;
	pst->top =0;  
}
void STPush(ST* pst,STDataType x)
{
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
		}
		pst->a = tmp;
		pst->capacity = newcapacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}
STDataType STTop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);
	return pst->a[pst->top - 1];
}
void STPop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);
	pst->top--;
}
bool STEmpty(ST* pst)
{
	assert(pst);
	return pst->top == 0;
}
bool isValid(char* s) 
{
   ST S;
   STInit(&S);
   while(*s)
   {
       if(*s=='['||*s=='('||*s=='{')
       {
           STPush(&S,*s);
           s++;
       }
       else
       {
           if(STEmpty(&S))
           {
               return false;
           }
           char top=STTop(&S);
           if(*s==']'&&top=='[')
           {
               STPop(&S);
               s++;
           }
           else if(*s=='}'&&top=='{')
           {
               STPop(&S);
               s++;
           }
           else if(*s==')'&&top=='(')
           {
               STPop(&S);
               s++;
           }
           else
           {
                return false;
           }
       }
   }
   if(STEmpty(&S))
   {
      return true;
   }
   return false;
}

碎碎念总结

你所看见的栈一定是你以为的栈吗(我在云什么(◎_◎;)),上面提到的栈是数据结构中的栈,还有一个“栈”是语言/操作系统中的栈,指一块内存区域。那么栈溢出是哪个概念呢?是操作系统中的栈,栈溢出指空间不够,在递归程序返回条件有问题的时候会出现栈溢出。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值