栈--顺序栈与链栈

  • 逻辑结构:线性表
  • 存储结构:顺序存储\链式存储
  • 基本运算:
    1. 初始化
    2. 判断栈空
    3. 判断栈满
    4. 入栈
    5. 出栈
    6. 取栈顶元素

注意:栈也是线性表,其特殊性在于有特殊的运算规则。即:栈结构只能在一端进行操作,该操作端称为栈顶,另一端称为栈底。按照“后进先出”(Last In First Out,LIFO)原则处理数据节点。

1. 顺序栈

  • 顺序栈的定义
typedef struct stack
{
    int *base;        	 	// 基地址
    int *top;          		// 栈顶指针
    int stackSize;          // 栈容量
}*Stack;
  • 顺序栈的初始化
Stack Init_Stack(Stack S)				// 栈的初始化
{
    S=(Stack)malloc(sizeof(Stack));
    if(!S)
        exit(0);
        
    S->base = (int*)malloc(STACK_INIT_SIZE*sizeof(DATATYPE));

    if(!S->base)
        exit(0);

    S->top = S->base;
    S->stackSize = STACK_INIT_SIZE;
    return S;
}
  • 判断栈空

栈底等于栈顶即为空。

int IsEmpty(Stack S)
{
    if (S->top == S->base){
        return 1;
    } 
	else{
        return 0;
    }
}
  • 判断栈满

栈顶减栈底等于栈容量即为栈满。

int IsFull(Stack S)
{
    if (S->top - S->base == S->stackSize) {
        return 1;
    } 
	else{
        return 0;

    }
}

回到目录

  • 顺序栈的入栈
void Push(Stack S, DATATYPE e)				// 数据压进栈
{
    assert(S);

    if (IsFull(S))

    {

        S->base = (int*)malloc((STACK_INIT_SIZE+STACK_INCREMENT)*sizeof(DATATYPE));

        if (!S->base)

            exit(0);       					 // 存储分配失败

        S->top = S->base + S->stackSize;

        S->stackSize += STACK_INCREMENT;

    }

    *S->top++ = e;

}
  • 顺序栈的出栈
DATATYPE Pop(Stack S)
{
    assert(S);
    if (S->top == S->base)
        return 0;     
    else
    {
        return *--S->top;     // *--S->top就是*(--S->top)
    }
} 
  • 取栈顶元素
// 访问栈顶 
DATATYPE GetTop(Stack S)
{
    assert(S);
    if (S->top == S->base)
        return 0;         
    else
    {
        return *(S->top-1);    
    }
} 

注意:取栈顶元素与出栈的区别:
出栈:数据从栈中移出,
取栈顶:只是访问了一下栈顶,数据还在栈中。

  • 顺序栈的销毁
void DestroyStack(Stack S) {
    free(S->base);
	free(S);
}

回到目录

  • 总的代码
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>             // 断言函数
#define STACK_INIT_SIZE 100     // 栈容量
#define STACK_INCREMENT 10      // 栈增量

typedef int DATATYPE;

typedef struct stack
{
    int *base;        	 // 基地址
    int *top;         	 // 栈顶指针
    int stackSize;       // 栈容量
}*Stack;


// 栈的初始化
Stack Init_Stack(Stack S)
{
    S=(Stack)malloc(sizeof(Stack));
    if(!S)
        exit(0);
        
    S->base = (int*)malloc(STACK_INIT_SIZE*sizeof(DATATYPE));

    if(!S->base)
        exit(0);

    S->top = S->base;
    S->stackSize = STACK_INIT_SIZE;
    return S;
}

// 判栈空
int IsEmpty(Stack S)
{
    if (S->top == S->base){
        return 1;
    } 
	else{
        return 0;
    }
}

// 判栈满
int IsFull(Stack S)
{
    if (S->top - S->base == S->stackSize) {
        return 1;
    } 
	else{
        return 0;

    }
}

// 操作数压栈
void Push(Stack S, DATATYPE e)
{
    assert(S);

    if (IsFull(S))
    {

        S->base = (int*)malloc((STACK_INIT_SIZE+STACK_INCREMENT)*sizeof(DATATYPE));

        if (!S->base)

            exit(0);        // 存储分配失败

        S->top = S->base + S->stackSize;

        S->stackSize += STACK_INCREMENT;

    }

    *S->top++ = e;
}

// 操作数弹栈
DATATYPE Pop(Stack S)
{
    assert(S);
    if (S->top == S->base)
        return 0;              // 空栈弹出0保证部分负数的正确运算
    else
    {
        return *--S->top;     // *--S->top就是*(--S->top)
    }
} 

// 访问栈顶 
DATATYPE GetTop(Stack S)
{
    assert(S);
    if (S->top == S->base)
        return 0;         
    else
    {
        return *(S->top-1);    
    }
} 

// 栈的销毁
void DestroyStack(Stack S) {
    free(S->base);
	free(S);
}

int main()
{
  	Stack OPND=NULL;
    OPND = Init_Stack(OPND);        // 创建操作数栈
	int i;
	for (i=0; i<5; i++)
    {
    	Push(OPND,i); 
    }
   
    for (i=0; i<5; i++)
    {
    	printf("此时的栈顶为:%d\n",GetTop(OPND));
    	printf("将%d出栈\n",Pop(OPND)); 
    }
    DestroyStack(OPND);
    return 0;

}

  • 运行结果

在这里插入图片描述
回到目录

2.链栈

  • 链栈的定义
typedef struct node			//定义节点
{
    DATATYPE data;
    struct node * next;
} StackNode;

typedef struct				//定义一个链栈
{
    StackNode * top;  		//总指向栈顶 
    int count;				//计数器 记录链栈的元素个数
}Stack,*LinkStack;
  • 链栈的初始化
void init(LinkStack s)
{
    s->top=NULL;		//该指针箭头指向为空
    s->count=0;			//初始化时长度为零
}
  • 判断栈空
int IsEmpty(LinkStack s)
{
    return (s->top==NULL? TRUE:FALSE);
}

回到目录

  • 链栈的入栈
void push(LinkStack s,DATATYPE a)
{
    StackNode * p=(StackNode *)malloc(sizeof(StackNode));
    if(NULL==p)				//申请不成功
        exit(1);
    else
    {
        p->data=a;			
        p->next=s->top;		//将新节点的指针域指向原栈顶节点
        s->top=p;			//栈顶指针指向新节点
        s->count++;
    }
}
  • 链栈的出栈
DATATYPE pop(LinkStack s)
{
    DATATYPE a; 
    if( IsEmpty(s))
        return FALSE;
    else
    {
        a =s->top->data;			//将即将弹出的数据存在a中。不存也不影响出栈操作 
        s->top=s->top->next;
        s->count--;
        free(s->top);		
		return a;
    }
}
  • 取栈顶元素
DATATYPE GetTop(LinkStack S)
{
    if(IsEmpty(S))
        return FALSE;
    else
    {
        return S->top->data;
    }
}

回到目录

  • 总的代码
# include<stdio.h>
# include<stdlib.h>
# define FALSE 0
# define TRUE 1

typedef int DATATYPE;

typedef struct node			//定义节点
{
    DATATYPE data;
    struct node * next;
} StackNode;

typedef struct				//定义一个链栈
{
    StackNode * top;  		//总指向栈顶 
    int count;				//计数器 记录链栈的元素个数
}Stack,*LinkStack;

void init(LinkStack s);					//初始化
int IsEmpty(LinkStack s);				//判断是否为空(链栈一般不会为满)
void push(LinkStack s,DATATYPE a);		//入栈
DATATYPE pop(LinkStack s);				//出栈
DATATYPE GetTop(LinkStack S);			//取栈顶元素
int length(LinkStack s);				//取链栈长度

void init(LinkStack s)
{
    s->top=NULL;		//该指针箭头指向为空
    s->count=0;			//初始化时长度为零
}

int IsEmpty(LinkStack s)
{
    return (s->top==NULL? TRUE:FALSE);
}

void push(LinkStack s,DATATYPE a)
{
    StackNode * p=(StackNode *)malloc(sizeof(StackNode));
    if(NULL==p)				//申请不成功
        exit(1);
    else
    {
        p->data=a;			
        p->next=s->top;		//将新节点的指针域指向原栈顶节点
        s->top=p;			//栈顶指针指向新节点
        s->count++;
    }
}

DATATYPE pop(LinkStack s)
{
    DATATYPE a; 
    if( IsEmpty(s))
        return FALSE;
    else
    {
        a =s->top->data;			//将即将弹出的数据存在a中。不存也不影响出栈操作 
        s->top=s->top->next;
        s->count--;
        free(s->top);		
		return a;
    }
}

DATATYPE GetTop(LinkStack S)
{
    if(IsEmpty(S))
        return FALSE;
    else
    {
        return S->top->data;
    }
}

int length(LinkStack s)
{
    return s->count;
}

int main(void)
{
    Stack S;
    init(&S);        // 创建操作数栈
 	int i;
	for (i=0; i<5; i++)
    {
    	push(&S,i); 
    }
    
    printf("链栈长度为:%d\n",length(&S));
    	
    while(!IsEmpty(&S))
    {    
		printf("此时的栈顶为:%d\n",GetTop(&S));  
        printf("将%d出栈\n",pop(&S)); 
    }
    return 0;
}
  • 运行结果

在这里插入图片描述

注意:顺序栈的栈顶指向的是即将入栈的位置,没有指着任何数据,所以栈顶减栈底可以判断是否为空或满。而链栈的指针指向的是栈顶的数据,所以s->top==NULL就可以判断是否为空。别搞混了。

回到目录

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值