数据结构与性质(2)栈(stack)基础板子

        一.栈的定义

        抛开算法,栈在字典中解释为"储存货物或供旅客住宿的房屋",可引申为仓库、中转站,例如我们现在生活中的酒店,在古时候叫客栈,供旅客休息的地方,旅客可以边客栈休息.,休息完毕就离开客栈。

        我们把生活中的栈类比到计算机中,可以猜想栈是供数据休息(即存储数据)的地方。事实上这么说也是正确的,数据既可以进栈,也可以出栈。栈是一种先进后出(FILO)的数据结构,是一种只能在一端进行加入和删除操作的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数封在栈顶,需要读数据的时候从栈顶开始(最后一个数被第一个读出来) 。

        实际上,栈某种意义上讲,它像是一个开口的盒子,先放进去的东西总是会被后放进去的东西压在下面,那么如果想拿出被压住的东西,必须要先取出顶部的东西,也就是后放进去的东西。换个说法就是先入后出。

 

        我们称数据进入栈的操作叫压栈,数据从栈中出去的操作叫弹栈。如果有n个元素进栈,出栈元素排序的方法为 种,以上公式称为卡特兰数(Catalan number , 1838年),会用就可以了。

        二.栈的顺序存储实现:(数据结构版)(代码很长,注释很仔细)(不知道自己咋肝出来的)

#include <cstdio>
#include <cstring>

#define MAXSIZE 10       // 顺序栈的最大长度。

typedef int ElemType;    // 自定义顺序栈的数据元素为整数。

typedef struct
{
  ElemType data[MAXSIZE];   // 用数组存储顺序栈中的元素。
  int top;                  // 栈顶指针,从0到MAXSIZE-1,-1表示空栈。
                            // 也可以从1到MAXSIZE,0表示空栈。
}SeqStack,*PSeqStack;

// 顺序栈SS的初始化操作。
void InitStack(PSeqStack SS);                     

// 销毁顺序栈SS。
void DestroyStack(PSeqStack SS);

// 元素入栈,返回值:0-失败;1-成功。
int Push(PSeqStack SS, ElemType *ee);

// 元素出栈,返回值:0-失败;1-成功。
int Pop(PSeqStack SS, ElemType *ee);

// 求顺序栈的长度,返回值:栈SS中元素的个数。
int Length(PSeqStack SS);                   

// 清空顺序栈。
void Clear(PSeqStack SS);                    

// 判断顺序栈是否为空,返回值:1-空,0-非空或失败。
int IsEmpty(PSeqStack SS);                    

// 判断顺序栈是否已满,返回值:1-已满,0-未满或失败。
int IsFull(PSeqStack SS);

// 打印顺序栈中全部的元素。
void PrintStack(PSeqStack SS);                    

// 获取栈顶元素,返回值:0-失败;1-成功。
// 只查看栈顶元素的值,元素不出栈。
int GetTop(PSeqStack SS, ElemType *ee);

int main()
{
  SeqStack SS;     // 创建顺序栈。

  InitStack(&SS);  // 初始化顺序栈。

  printf("栈的长度是%d\n",Length(&SS));

  ElemType ee;     // 创建一个数据元素。

  printf("元素(1、2、3、4、5、6、7、8、9、10)入栈。\n");
  ee=1;  Push(&SS, &ee);
  ee=2;  Push(&SS, &ee);
  ee=3;  Push(&SS, &ee);
  ee=4;  Push(&SS, &ee);
  ee=5;  Push(&SS, &ee);
  ee=6;  Push(&SS, &ee);
  ee=7;  Push(&SS, &ee);
  ee=8;  Push(&SS, &ee);
  ee=9;  Push(&SS, &ee);
  ee=10; Push(&SS, &ee);

  printf("栈的长度是%d\n",Length(&SS));

  // 只查看栈顶元素的值,元素不出栈。
  if (GetTop(&SS,&ee)==1)  printf("栈顶的元素值为%d\n",ee);

  PrintStack(&SS);

  if (Pop(&SS,&ee)==1)  printf("出栈的元素值为%d\n",ee);
  if (Pop(&SS,&ee)==1)  printf("出栈的元素值为%d\n",ee);
  if (Pop(&SS,&ee)==1)  printf("出栈的元素值为%d\n",ee);
  if (Pop(&SS,&ee)==1)  printf("出栈的元素值为%d\n",ee);
  if (Pop(&SS,&ee)==1)  printf("出栈的元素值为%d\n",ee);
  if (Pop(&SS,&ee)==1)  printf("出栈的元素值为%d\n",ee);
  if (Pop(&SS,&ee)==1)  printf("出栈的元素值为%d\n",ee);
  if (Pop(&SS,&ee)==1)  printf("出栈的元素值为%d\n",ee);
  if (Pop(&SS,&ee)==1)  printf("出栈的元素值为%d\n",ee);
  if (Pop(&SS,&ee)==1)  printf("出栈的元素值为%d\n",ee);
  if (Pop(&SS,&ee)==1)  printf("出栈的元素值为%d\n",ee);
  if (Pop(&SS,&ee)==1)  printf("出栈的元素值为%d\n",ee);

  return 0;
}

// 初始化顺序栈
void InitStack(PSeqStack SS)
{
  Clear(SS); // 清空顺序栈。
}

// 清空顺序栈。
void Clear(PSeqStack SS)
{
  if (SS == NULL) return; // 检查空指针。

  SS->top=-1;  // 栈顶指针置为-1。
  memset(SS->data,0,sizeof(ElemType)*MAXSIZE);  // 数组元素清零。
}

// 求顺序栈的长度,返回值:栈SS中元素的个数。
int Length(PSeqStack SS)
{
  if (SS == NULL) return 0; // 检查空指针。

  return SS->top+1;
}

// 销毁顺序栈SS。
void DestroyStack(PSeqStack SS)
{
  // 静态顺序栈无需释放内存,不需要销毁操作。

  Clear(SS); // 清空顺序栈。

  return;
}

// 判断顺序栈是否为空,返回值:1-空,0-非空或失败。
int IsEmpty(PSeqStack SS)
{
  if (SS == NULL) return 0;  // 检查空指针。

  if (SS->top == -1) return 1;

  return 0;
}

// 判断顺序栈是否已满,返回值:1-已满,0-未满或失败。
int IsFull(PSeqStack SS)
{
  if (SS == NULL) return 0;  // 检查空指针。

  if (SS->top >= MAXSIZE-1) return 1;

  return 0;
}

// 元素入栈,返回值:0-失败;1-成功。
int Push(PSeqStack SS, ElemType *ee)
{
  if ( (SS == NULL) || (ee == NULL) ) return 0;  // 检查空指针。

  if (IsFull(SS) == 1)
  {
    printf("顺序栈已满,不能插入。\n"); return 0;
  }

  SS->top++;  // 栈指针先加1。

  memcpy(&SS->data[SS->top],ee,sizeof(ElemType));  // 用数组的下标访问。
  // memcpy(SS->data+SS->top,ee,sizeof(ElemType));    // 采用指针运算也可以。

  return 1;
}

// 打印顺序栈中全部的元素。
void PrintStack(PSeqStack SS)
{
  if (SS == NULL) return;  // 检查空指针。

  if (SS->top == -1) { printf("栈为空。\n"); return; }

  int kk;
  for (kk = 0; kk <= SS->top; kk++)
  {
    printf("SS[%d],value=%d\n",kk,SS->data[kk]);     // 用数组的下标访问。
    // printf("SS[%d],value=%d\n",kk,*(SS->data+kk));   // 采用指针运算也可以。
  }
}

// 元素出栈,返回值:0-失败;1-成功。
int Pop(PSeqStack SS, ElemType *ee)
{
  if ( (SS == NULL) || (ee == NULL) ) return 0;  // 检查空指针。

  if (SS->top == -1) { printf("栈为空。\n"); return 0; }

  memcpy(ee,&SS->data[SS->top],sizeof(ElemType));  // 用数组的下标访问。
  // memcpy(ee,SS->data+SS->top,sizeof(ElemType));    // 采用指针运算也可以。

  SS->top--;  // 栈指针减1。

  return 1;
}

// 获取栈顶元素,返回值:0-失败;1-成功。
// 只查看栈顶元素的值,元素不出栈。
int GetTop(PSeqStack SS, ElemType *ee)
{
  if ( (SS == NULL) || (ee == NULL) ) return 0;  // 检查空指针。

  if (IsEmpty(SS) == 1) { printf("栈为空。\n"); return 0; }

  memcpy(ee,&SS->data[SS->top],sizeof(ElemType));  // 用数组的下标访问。
  // memcpy(ee,SS->data+SS->top,sizeof(ElemType));    // 采用指针运算也可以。

  return 1;
}

 最终结果:

 

        三.栈的常用接口(C++中STL的使用):

        构造函数:

stack<T> stk;//stack采用模板类实现, stack对象的默认构造形式
stack(const stack &stk); //拷贝构造函数

        赋值操作:

stack& operator=( const stack &stk) ;//重载等号操作符

        数据存取:

push(elem);//向栈顶添加元素
pop();//从栈顶移除第一个元素
top();//返回栈顶元素

         大小操作:

empty();//判断堆栈是否为空
size();//返回栈的大小

         操作案例:

#include<iostream>
#include<stack> 
using namespace std;
//栈stack容器
void test12()
{
	//特点:符合先进后出数据结构 
	stack<int>s;
	
	//入栈
	s.push(10); 
	s.push(20); 
	s.push(30); 
	s.push(40);
	 
	cout<<"栈的大小: "<<s.size()<<endl; 
	//只要栈不为空,查看栈顶,并且执行出栈操作
	while(!s.empty())
	{
		//查看栈顶元素
		cout<<"栈顶元素为: "<<s.top()<<endl;
		
		//出栈
		s.pop(); 		 
	}

	cout<<"栈的大小: "<<s.size()<<endl; 
} 

int main()
{
	test12();
	return 0;
}
/*总结:入栈---push
	   出栈---pop
       返回栈顶---top
	   判断栈是否为空-----empty
	   返回栈的大小----size
*/ 

 

 

 

 

 

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

华梦天下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值