堆栈的三种实现方式

Posted Carrie_0173

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了堆栈的三种实现方式相关的知识,希望对你有一定的参考价值。

  传统的堆栈操作只有 入栈push 和 出栈pop 两种,没有单独的访问栈顶元素的操作,访问栈顶元素的唯一方式就是出栈(pop会把堆栈顶部的值移出堆栈并返回这个值)。这样的pop存在副作用。

  所以,我们在这里实现提供push、pop、top三种基本操作的堆栈。

实现堆栈这一抽象数据类型(ADT),即要实现:入栈(push)、出栈(pop)、访问栈顶元素(top)的操作,另外加上两个判断 栈满、栈空与否的函数。

通常,我们可以使用 静态数组动态数组动态链表 这三种方式来实现堆栈。

首先,在stack.h文件中声明 操作函数 以及 定义 堆栈的存储类型。这个文件,通用于下面的三种实现方式,且在修改堆栈存储类型时,只需简单修改此文件即可。

stack.h:

#define STACK_TYPE int //堆栈存储的值的类型

//入栈
void push(STACK_TYPE value);

//出栈
void pop(void);

//访问栈顶元素
STACK_TYPE top(void);

//判断是否栈空
int is_empty(void);

//判断是否栈满
int is_full(void);

一、静态数组方式实现堆栈

stack1.c:  此种方法实现的堆栈,要修改堆栈长度只能修改该源文件中的STACK_SIZE值,并重新编译才可。

#include "stack.h"
#include <assert.h>  //包含了 assert宏

#define STACK_SIZE 100  //堆栈中所存元素的最大数量

static STACK_TYPE stack[STACK_SIZE];//堆栈数组
static top_element = -1;  //栈顶元素标识
//定义为static 使其只能在声明它们的源文件中被访问

//入栈push
void push(STACK_TYPE value){
        //栈满则不能再入栈,首先要判断是否栈满  
        assert(!is_full());  //assert宏,对表达式参数测试,若值为假,则打印错误信息并终止程序
        top_element +=1;
        stack[top_element] = value;  
}

//出栈pop
void pop(void){
        //栈空则不能再出栈,首先要判断是否栈空
        assert(!is_empty());
        top_element -=1;  
}

//访问栈顶元素top
STACK_TYPE top(void){
        assert(!is_empty());
        return stack[top_element];
}

//判断是否栈满is_full
int is_full(void){
        return top_element == STACK_SIZE-1;
}

//判断是否栈空is_empty
int is_empty(void){
        return top_element == -1;
}

二、动态数组方式实现堆栈

stack2.c:  此种方法实现的堆栈,堆栈的长度在调用创建堆栈函数时,以函数参数的形式给出。

#include "stack.h"
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <assert.h>

static STACK_TYPE *stack;//堆栈指针
static size_t static_size; //保存堆栈可容纳元素个数的变量 stack_size 存储于全局存储区BSS段,将被初始化为0
static int top_element = -1;//栈顶元素标识

//创建堆栈的函数create_stack
void create_stack(size_t size){
        assert(stack_size == 0); //若stack_size!=0则说明堆栈已经创建
        stack_size = size;  //size为堆栈可容纳元素的个数
        stack = malloc(stack_size * sizeof(STACK_TYPE));
        assert(stack != NULL);//检验堆栈是否成功创建
}

//销毁堆栈destroy_stack
void destroy_stack(void){
        assert(stack_size > 0);
        stack_size = 0;
        free(stack);   //销毁堆栈,防止内存泄露
        stack = NULL;
}

//push
void push(STACK_TYPE value){
        assert(!is_full());
        top_element +=1;
        stack[top_element] = value;
}

//pop
void pop(void){
        assert(!is_empty());
        top_element -=1;
}

//top
STACK_TYPE top(void){
        assert(!is_empty());
        return stack[top_element];
}

//is_full
int is_full(void){
        assert(stack_size > 0);
        return top_element == stack_size-1;
}

//is_empty
int is_empty(void){
        assert(stack_size > 0);
        return top_element == -1;
}

三、动态链表方式实现堆栈

stack3.c: 此种实现方式,不需要单独提前创建堆栈,但要注意堆栈的销毁,以避免内存泄露。

#include "stack.h"
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <assert.h>

#define FALSE 0

//定义链表节点,用于存储堆栈元素
typedef struct STACK_NODE{
        STACK_TYPE value;
        struct STACK_NODE *next;
}StackNode;

//指向堆栈第一个节点的指针
static StackNode *stack;

//用于清空堆栈的函数,防止内存泄露
void destroy_stack(void){
        while(!is_empty())
                pop();
}

//push
void push(STACK_TYPE value){
        StackNode *new_node;
        new_node = malloc(sizeof(StackNode));
        new_node->value = value;
        new_node->next = stack;
        stack = new_node;
}

//pop
void pop(void){
        StackNode *delete_node;
        assert(!is_empty());
        delete_node = stack;
        stack = stack->next;
        free(delete_node);
}

//top
Stack_TYPE top(void){
        assert(!is_empty());
        return stack->value;
}

//is_full
int is_full(void){
        return FALSEE; //堆栈长度除受内影响外,没有长度限制
}

//is_empty
int is_empty(void){
        return stack == NULL;
}

 

以上是关于堆栈的三种实现方式的主要内容,如果未能解决你的问题,请参考以下文章

Java 多线程实现的三种方式

java 代理的三种实现方式

mysql读写分离的三种实现方式

基于Java的二叉树的三种遍历方式的递归与非递归实现

IOS实现毛玻璃效果的三种方式

java实现HTTP请求的三种方式