浅谈基础算法之堆栈(五) - 川山甲 - 博客园

浅谈基础算法之堆栈(五) - 川山甲 - 博客园

目录
 
 
 
我一直在想一个问题,我怎么能把一件事情说的明白呢?尤其是程序方面的知识点。思路清楚是非常重要的(只有思路清楚,表达清楚了,才能一目了然),这个清楚的思路怎么表现出来?我努力去做这件事情。这篇主要围绕堆栈来展开话题。
 
 
 
堆栈是什么?
 
 
 
 
实现方式
 
 
 
静态数组堆栈
 
 
1、先把你要做的事情准备好。
复制代码
/* ===========数据 */
#define STACK_INIT_MAXSIZE 100
char stack[STACK_INIT_MAXSIZE];
int top = -1;


/* ===========操作  */
void push(){
}

void pop(){
}

char get_top(){
}

int is_empty(){
}

int is_full(){
}
复制代码

这么一罗列,一下就明朗了!

2、开始逐步实现每一个函数。

 
复制代码
/* 
 * 用一个静态数组实现堆栈
 *
 * (C) Copyright 2013 Chuan Shanjia
 */
#include <stdio.h>
#include <assert.h>


#define STACK_INIT_MAXSIZE 100
char stack[STACK_INIT_MAXSIZE];
int top = -1;


/* ===========基本操作  */
void push(char *value) {
    assert(!is_full());
    stack[++top] = *value;
}

void pop() {
    assert(!is_empty());
    top--;
}
char get_top() {
    assert(!is_empty());
    return stack[top];
}

/* ===========额外操作 */
int is_empty(){
    return top == -1;
}
int is_full(){
    return top == STACK_INIT_MAXSIZE - 1;
}
复制代码
 

top存储堆栈顶部元素的下标值。开始由于没有顶部元素,所以初始值为-1,提示堆栈为空。

pop函数不需要从数组中删除元素,只减少顶部元素的下标值就足矣。

 

3、现在测试一下上面的堆栈的正确性(在上面的代码文件中,添加如下代码)。

复制代码
void print_stack(){
    int i = top;
    for(; i >= 0; i--){
        printf("%c ", stack[i]);
    }

    printf("\t");
    printf("栈顶元素:%c", get_top());
}

int main() {
    char c;
    scanf("%c", &c);
    while(c != '#'){
        if(c != '\n')
            push(&c);
        scanf("%c", &c);
    }

    printf("========打印堆栈\n");
    print_stack();
    printf("\n");

    printf("========出栈一次,打印堆栈\n");
    pop();
    print_stack();
    printf("\n");
    return 0;
}
复制代码

打印结果如下:

 

 
动态数组堆栈
 
动态数组的特点:运行时才决定数组大小。——故需在原有的操作上,添加几个操作。
 
1、先把你要做的事情准备好。
复制代码
/* ===========数据 */
char *stack;
int stack_size;
int top = -1;


/* ===========操作  */
void create_stack(){
}   

void destroy_stack(){
}   

void push(){
}

void pop(){
}

char get_top(){
}

int is_empty(){
}

int is_full(){
}
复制代码

2、开始逐步实现每一个函数。

复制代码
#include <stdio.h>
#include <assert.h>
#include <malloc.h>

/* ===========数据 */
char *stack;
int stack_size;
int top = -1;


/* ===========操作  */
void create_stack(int size){
    assert(size > 0); 
    stack_size = size;
    stack = (char *)malloc(stack_size * sizeof(char));
    assert(stack != NULL);
}

void destroy_stack(){
    assert(stack_size > 0); 
    free(stack);
    stack_size = 0;
    stack = NULL;
}

void push(char *value){
    assert(!is_full());
    stack[++top] = *value;
}

void pop(){
    assert(!is_empty());
    --top;
}

char get_top(){
    assert(!is_empty());
    return stack[top];
}

int is_empty(){
    assert(stack_size > 0);
    return top == -1;
}

int is_full(){
    assert(stack_size > 0);
    return top == stack_size - 1;
}
复制代码

 

3、现在测试一下上面的堆栈的正确性(在上面的代码文件中,添加如下代码)。

复制代码
void print_stack(){
    int i = top;
    for(; i >= 0; i--){
        printf("%c ", stack[i]);
    }

    printf("\t");
    printf("栈顶元素:%c", get_top());
}

int main() {
    char c;
    create_stack(100);

    scanf("%c", &c);
    while(c != '#'){
        if(c != '\n')
            push(&c);
        scanf("%c", &c);
    }

    printf("========打印堆栈\n");
    print_stack();
    printf("\n");

    printf("========出栈一次,打印堆栈\n");
    pop();
    print_stack();
    printf("\n");

    destroy_stack();
    return 0;

}
复制代码
 
打印结果如下:
 
 
动态分配的链式结构堆栈(又名链式堆栈)
 
 
 
push和pop我们可以这样考虑,就是移动最后一个节点上的指针。push就把最后一个节点指针向后移动一位,pop就把指针向前移动一位。
 
1、先把你要做的事情准备好。
 
复制代码
struct stack_node{
    char data;
    struct stack_node *prev;
};

struct stack_node *current;

/* ===========基本操作  */
void push(){
}

void pop(){
}

char get_top(){
}

/* ===========额外操作 */
int is_empty(){
}
void destroy(){
}
复制代码

 2、开始逐步实现每一个函数。

复制代码
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

struct stack_node{
    char data;
    struct stack_node *prev;
};

struct stack_node *current;

/* ===========基本操作  */
void push(char *value){
    struct stack_node *new = (struct stack_node *)malloc(sizeof(struct stack_node));
    assert(new != NULL);
    new->data = *value;
    new->prev = current;
    current = new;
}

void pop(){
    assert(!is_empty());
    struct stack_node *last_node = current;
    current = current->prev;
    free(last_node);
}   

char get_top(){
    assert(!is_empty());
    return current->data;
}

/* ===========额外操作 */
int is_empty(){
    return current == NULL;
}   

void destroy(){
    while(!is_empty()){
        pop();
    }
}
复制代码

 

3、现在测试一下上面的堆栈的正确性(在上面的代码文件中,添加如下代码)。

复制代码
void print_stack(){
    struct stack_node *print_node = current;
    while(print_node != NULL){
        printf("%c ", print_node->data);
        print_node = print_node->prev;
    }

    printf("\t");
    printf("栈顶元素:%c", get_top());
}
    
int main() {
    char c;
    
    scanf("%c", &c);
    while(c != '#'){
        if(c != '\n')
            push(&c);
        scanf("%c", &c);
    }
    
    printf("========打印堆栈\n");
    print_stack();
    printf("\n");

    printf("========出栈一次,打印堆栈\n");
    pop(); 
    print_stack();
    printf("\n");

    destroy_stack();
    return 0;

}
复制代码

打印结果如下:

 

 
 
总结
 
以上三种方案我们要找到它们的特点:
静态数组堆栈要求结构的长度固定。而且这个要在编译时确定(我们用define定义)。——此方案最简单、最不容易出错。
 
动态数组堆栈我们可以在运行时才决定数组的长度。——在复杂性和平衡性之间做权衡。
 
 
链式结构堆栈每个元素在需要时才单独进行分配,这种方式对元素的数量几乎没有限制(排除考虑内存大小)。——最大程度的灵活性,需要消耗一定的内存,访问特定元素的效率不如数组。
 
最后,希望我的这篇博文对你有所帮助。
 
推荐
 
 
 
喜欢编程
标题基于Python的自主学习系统后端设计与实现AI更换标题第1章引言介绍自主学习系统的研究背景、意义、现状以及本文的研究方法和创新点。1.1研究背景与意义阐述自主学习系统在教育技术领域的重要性和应用价值。1.2国内外研究现状分析国内外在自主学习系统后端技术方面的研究进展。1.3研究方法与创新点概述本文采用Python技术栈的设计方法和系统创新点。第2章相关理论与技术总结自主学习系统后端开发的相关理论和技术基础。2.1自主学习系统理论阐述自主学习系统的定义、特征和理论基础。2.2Python后端技术栈介绍DjangoFlask等Python后端框架及其适用场景。2.3数据库技术讨论关系型和非关系型数据库在系统中的应用方案。第3章系统设计与实现详细介绍自主学习系统后端的设计方案和实现过程。3.1系统架构设计提出基于微服务的系统架构设计方案。3.2核心模块设计详细说明用户管理、学习资源管理、进度跟踪等核心模块设计。3.3关键技术实现阐述个性化推荐算法、学习行为分析等关键技术的实现。第4章系统测试与评估对系统进行功能测试和性能评估。4.1测试环境与方法介绍测试环境配置和采用的测试方法。4.2功能测试结果展示各功能模块的测试结果和问题修复情况。4.3性能评估分析分析系统在高并发等场景下的性能表现。第5章结论与展望总结研究成果并提出未来改进方向。5.1研究结论概括系统设计的主要成果和技术创新。5.2未来展望指出系统局限性并提出后续优化方向。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值