【第三章】栈

基本概念

Stack是只允许在一端进行插入和删除的线性表

常见术语

栈顶(允许进行插入和删除的一端)        栈底        空栈

特点

LIFO        卡特兰数 

 栈的基本操作(创/销/增/删/查/判空,判满)

InitStack(&S)   DestoryStack(&S)   Push(&S,x)   Pop(&S,&x)   GetTop(S,&x)   StackEmpty(S)

栈的顺序存储结构

利用一组地址连续空间,同时设一个top指针指示当前栈顶元素的位置

空间不足会导致上溢

//顺序栈
#include<stdio.h>
#include<stdlib.h>
#define MaxSize 50

/*
InitStack(&S)
DestoryStack(&S)
Push(&S,x)
Pop(&S,&x)
GetTop(S,&x)
StackEmpty(S)   */

typedef struct{
	int data[MaxSize];
	int top;
}SqStack;   //顺序栈

void InitStack(SqStack &S){
	S.top=-1;   //初始化栈顶指针,其实也可以初始化为0 
} 

//bool DestoryStack(SqStack &S){
//	
//} 

bool Push(SqStack &S,int x){   //进栈 
	if(S.top==MaxSize-1)
		return false;   //进栈时首先判满
	S.data[++S.top]=x;
	return true; 
}

bool Pop(SqStack &S,int &x){  //出栈 
	if(S.top==-1)
		return false;  //出栈时首先判断是否是空栈
	x=S.data[S.top--]; 
	return true;
} 

bool GetTop(SqStack S,int &x){  //读取栈顶元素 
	if(S.top==-1)
		return false;  //首先判断是否是空栈
	x=S.data[S.top];
	return true; 
}

bool StackEmpty(SqStack S){  //判空 
	if(S.top==-1)
		return true;
	else
		return false;
}

int main(){
	SqStack S;
	int x,y=0;
	scanf("%d",&x);
	InitStack(S);
	Push(S,x);
	GetTop(S,y);
	printf("%d",y);
}

书上将顺序表唯一的指针初始化为-1,也可以初始化为0。

共享栈

两个指针top0和top1,top为-1,top1为MaxSize;当两个指针之间相差一,则满(top1-top0=1),只是为了有效地利用存储空间,时间复杂度还是为O(1),对存储效率没有什么影响。

//共享栈
#include<stdio.h>
#include<stdlib.h>
#define MaxSize 50

/*
InitStack(&S)
DestoryStack(&S)
Push(&S,x)
Pop(&S,&x)
GetTop(S,&x)
StackEmpty(S)   */

typedef struct{
	int data[MaxSize];
	int top0;
	int top1;
}ShStack;   //共享栈

void InitStack(SqStack &S){
	S.top0=-1;   //初始化指针,其实也可以初始化为0 
	S.top1=MaSize;
} 
/*
以下出栈,进栈,判空,读栈顶元素函数方法都相类似 
*/
 栈的链式存储结构

链栈优点:便于多个栈共享存储空间和提高其效率,通常采用单链表实现。并规定所有的操作都是在单链表的表头进行的,书上规定,链栈没有头节点,Lhead指向栈顶元素。

注意】带头节点和不带头节点的链栈,具体实现会有所不同

【不懂】上图中7行,声明一个指针,不是应该写为struct LinkNode *next吗?难道这个struct可以省略。                                                                                                                                 
// 链栈
#include<stdio.h>
#include<stdlib.h>

//定义结构体 
typedef struct LinkNode{
	int data;
	//Node *next; 这样写报错
	LinkNode *next;  //前面写不写struct都不会报错 
}Node, *LiStack;

//初始化栈 
void InitStack(LiStack &S){
	S=NULL;
} 

//判断空栈
bool StackEmpty(LiStack S){
	if(S==NULL)
		return true;
	else
		return false;
} 

//进栈
bool Push(LiStack &S,int x){
	//不需要判空判满
	Node *p=(Node *)malloc(sizeof(Node));
	//因为p为指针,故不能p.data=x;p.next=S这样
	p->data=x;
	p->next=S;  //相当于头插法 
	S=p;
	return true;
} 

//出栈
bool Pop(LiStack &S,int &x){
	//出栈需要判断栈是否为空
	if(S==NULL)
		return false;
	/*
	x=S->data;
	S=S->next;
	return true;  这样写出错误,因为没有释放这个节点*/
	Node *p=S;    //这样写还是通过malloc函数写? 
	x=p->data;
	S=p->next;
	free(p);
	return true; 
} 

//取栈顶元素
bool GetTop(LiStack S,int &x){
	//判空
	if(S==NULL)
		return false;
	x=S->data;
	return true; 
} 

//销栈 
void DestoryStack(LiStack &S){
	int e;
	while(S!=NULL)
		Pop(S,e);
	free(S);
} 

void Proint(LiStack S){
	if(StackEmpty(S)){
		printf("空栈\n");
		return;//也可以不用写这句
	}
	Node *p=S;
	while(p!=NULL){
		printf("%d  ",p->data);
		p=p->next; 
	}
	printf("\n");
}




int main(){
    LiStack S;
    printf("***************************************\n");
    printf("********  1.初始化栈  2.空栈判断  ********\n");
    printf("********  3. 进 栈   4. 出 栈   ********\n");
    printf("********  5.读取栈顶  6. 销 栈   ********\n");
    printf("********  7. 遍 历   0. 退 出   ********\n");
    printf("***************************************\n");
    bool flag= true;
    int x;
    int e;
    while(flag) {
        printf("请输入命令:");
        scanf("%d", &x);
        switch (x) {
            case 1:
                InitStack(S);
                printf("\t空栈初始化完成\n");
                break;
            case 2:
                if (StackEmpty(S)) printf("\t该栈是空栈\n");
                else printf("\t该栈不是空栈\n");
                break;
            case 3:
                printf("\t请输入要进栈的元素:");
                int a;
                scanf("%d", &a);
                if (Push(S, a))printf("\t元素进栈成功\n");
                else printf("\t元素进栈失败\n");
                break;
            case 4:
                if (Pop(S, e))
                    printf("\t元素出栈成功,出栈的元素为:%d\n", e);
                else
                    printf("\t元素进栈失败\n");
                break;
            case 5:
                if (GetTop(S, e))
                    printf("\t栈顶元素为:%d\n", e);
                else
                    printf("\t该栈为空栈\n");
                break;
            case 6:
                DestoryStack(S);
                printf("\t销毁成功\n");
                break;
            case 7:
                printf("\t当前栈中元素:");
                Proint(S);
                break;
            case 0:
                printf("退出成功\n");
                flag = false;
                break;
            default:
                printf("命令错误,请重新输入!!!");
                break;
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

云上成理

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

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

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

打赏作者

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

抵扣说明:

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

余额充值