数据结构学习笔记第五节:栈

一、栈的定义

栈(stack)是限定仅在表位进行插入和删除操作的线性表。

我们把允许插入和删除的一端称为栈顶(top),另外一端称为栈底(bottom),不含任何元素的栈称为空栈。栈又被称为先进后出的线性表,简称LIFO结构。

理解栈的定义需要注意以下几点:

首先它是一个线性表,也就是说,栈元素具有线性关系,即前驱后继关系。只不过它是一种特殊的线性表而已。定义中说是在线性表的表尾进行插入和删除操作,这里表尾是指栈顶而不是栈底。

栈的特殊之处在于限制了这个线性表的插入和删除的位置,它始终只在栈顶进行,这也就使得:栈底是固定的,最先进栈的智能在栈底。

栈的插入操作,叫做进栈,也称为压栈,入栈。

栈的删除操作,叫作出栈,也称为弹栈。

二、进栈出栈的变化形式

首先大家要弄清楚一个问题:最先进栈的元素是不是就只能最后出栈呢?

答案是不一定的,要看什么情况。栈对线性表的插入和删除的位置进行了限制,并没有对元素的进出时间进行限制,也就是说,在不是所有元素都进栈的情况下,事先进去的元素也可以出栈,只要保证是栈顶元素出栈就可以。

三、栈的顺序存储结构及实现

3.1栈的顺序存储结构

栈是线性表的特例,那么栈的顺序存储结构其实也是线性表的顺序存储结构的简化,我们简称为顺序栈。

栈的结构定义C代码:

#include<stdio.h>
#define MAXSIZE 20
typedef int ElemType  
typedef struct
{
    Elemtype data[MAXSIZE];
    int top;     /*用于栈顶指针*/ 
}SqStack;

3.2栈的顺序存储结构——栈的初始化操作C实现

void Init_Stack(SqStack *S)
{
    S->top=-1;
}

3.3栈的顺序存储结构——进栈操作C实现

Status Push(SqStack *S, ElemType e)
{
	if(S->top == MAXSIZE -1)  // 栈满
	{
		printf("栈已满,不能进行插入操作!!!"); 
		return FALSE;
	} 
	S->top++;             //栈顶指针加1 
	S->data[S->top] = e;  //将性插入的元素赋值给栈顶空间 
	return OK;
	
}

3.4栈的顺序存储结构——出栈操作C实现

Status Pop(SqStack *S, ElemType *e)
{
	if(S->top == -1)
	{
		prinitf("此栈为空!\n");
		return FALSE; 
	}
	*e = S->data[S->top];   //取出出栈的元素 
	S->top--;               //栈顶指针减1
	return OK; 
}

3.5栈的顺序存储结构——栈的遍历操作C实现

Status StackTravel(SqStack *S)
{
	int i = 0; 
	for(i = 0 ; i <= S->top; i++)
	{
		printf("  %d",S->data[i]);
    }  
}

3.6栈的顺序存储结构——栈的各种操作实现C++

1.用C++自带的库实现:

/*
#include<stack>
s.empty()               如果栈为空返回true,否则返回false
s.size()                返回栈中元素的个数
s.pop()                 删除栈顶元素但不返回其值
s.top()                 返回栈顶的元素,但不删除该元素
s.push()                在栈顶压入新元素
*/
#include <iostream>
#include <stack>
 
using namespace std;
 
int main(void) {
	stack<int> st;
	int len=0;
	st.push(4);
	st.push(3);
	st.push(2);
	st.push(1);
	st.push(0);
 
	cout<<"size is "<<st.size()<<endl;
	cout<<"top elem is "<<st.top()<<endl;
	len=st.size();
	for(int i=0;i<len;i++)
	{
		cout<<"After pop, The "<<i<<"th top elem is "<< st.top()<<endl;
		st.pop();
	}
	return 0;
}

四、栈的链式存储结构及实现

前面写了顺序存储结构的C和C++实现,我们现在来看看栈的链式存储结构简称链栈。通常来说链栈是不需要头结点的。对于链栈来说,基本不存在栈满的情况,除非内存已经没有可以使用的空间,如果真的发生,那此时的计算机操作系统已经面临死机崩溃的情况,而不是这个链栈是否溢出的问题。

但对于空栈来说,链表原定义是头指针指向空,那么链栈的空其实就是top = NULL的时候。链栈的结构代码如下:

#include <stdio.h>
#include <stdlib.h>
#include<malloc.h>
#define false  -1
#define true    1
typedef int bool;
typedef int ElemType ; 
typedef struct StackNode{
	ElemType data;
	struct StackNode *Next;
}StackNode,*LinkStackPtr; 

typedef struct LinkStack{
	LinkStackPtr top;
	int count;
}LinkStack;

4.1链栈——进栈操作

对于连栈的Push操作,假设元素值为e的新结点是s,top为栈顶指针,其代码如下所示:

//链式存储进栈操作
 bool Push(LinkStack *S, ElemType e)
{
	LinkStackPtr s = (LinkStackPtr)malloc(sizeof(StackNode));
	s->data = e;
	s->Next = S->top;    //当前的栈顶元素赋值给新结点的直接后继 
	S->top = s;       //新的节点赋值给栈顶指针 
	S->count++;
	return true;
 } 
 

4.2 连栈——出栈操作

假设变量p用来存储要删除的栈顶结点,将栈顶指针下移一位,最后释放p即可

bool Pop(LinkStack *S, ElemType *e)
 {
 	LinkStackPtr P;
 	if(S->count == 0)
 	{
 		printf("栈为空!!\n");
 		return false;
	 }
 	*e = S->top->data;
	 P = S->top;
	 S->top = S->top->Next;
	 free(P);
	 S->count--; 
  } 

4.3连栈——其它常见操作

//栈的初始化
bool InitStack(LinkStack *S)
  {
  	S->top = (LinkStackPtr)malloc(sizeof(StackNode));
  	if(!S->top)
  	return false;
  	S->top = NULL;
  	S->count = 0;
  	return true;
  }
  
  //把栈置空
  bool ClearStack(LinkStack *S)
  {
  	LinkStackPtr p,q;
  	p = S->top;
  	while(p)
  	{
  		q = p ;
  		p = p->Next;
  		free(q);
	  }
	  S->count = 0;
	  return true;
   } 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值