Linux笔记 --- 栈

我们可以通过顺序存储的方式来实现栈逻辑,这种栈叫做顺序栈,也可以通过链式存储的方式实现,这种栈叫做链式栈,存储结构的异同不影响栈先进后出的特性

顺序栈

顺序栈的实现主要就是定义一块连续内存存放栈元素,为了方便管理创建一个整形数据代表栈顶元素在此连续内存中的偏移,这样可以很方便的知道此栈的状态和栈顶元素位置,便于压栈和出栈,我们将这些元素存放在同一个管理结构体中,根据我们的思路,顺序栈可以用以下代码来表示:

cpp 复制代码
struct sequent_stack
{
    int *stack; //指向用以存放栈元素的连续内存
    int size;   //保存该数据栈的总大小
    int top;    //表示栈顶元素的偏移量
};

初始化

有了结构体我们就要考虑该如何初始化这个栈,首先将stack指向的内存清零,其次将top置为-1并规定-1为空栈,这么做的好处是,压栈第一个元素后top+1就成了0,第一个元素偏移为0

cpp 复制代码
struct sequent_stack *stack_init(int size)
{
    struct sequent_stack *s;
    s = malloc(sizeof(struct sequent_stack));

    if(s != NULL)
    {
        s->stack = calloc(size,sizeof(int));    
        //CALLOC函数相比于malloc的区别在于会在分配之后将内存设置为0
        s->size = size;
        s->top = -1;
    }
    return s;
}

有了初始化的栈,接下来就是编写一些基本操作

压栈

压栈的第一步要判断栈是否已满,如果未满则将元素置于栈顶,已满则进行扩充或者错误退出:

cpp 复制代码
bool stack_full(struct sequent_stack *s)
{
    return s->top >= s->size-1;
}

bool push(struct sequent_stack *s,int data)
{
    if(stack_full(s))
    return false;

    s->top++;
    s->stack[s->top] = data;
    return true;
}

出栈

出栈中因为要返回bool值表示是否成功,所以要获取一个参数来存放出栈的元素,其次在出栈前要先判断是否为空栈

cpp 复制代码
bool stack_empty(struct sequent_stack *s)
{
    return s->top == -1;
}

bool pop(struct sequent_stack *s,int *p)
{
    if(stack_empty(s))
        return false;
    
    *p = s->stack[s->top];
    s->top--;

    return true;
}

结合上面的操作我们可以使用栈操作进行十进制转8进制的操作

cpp 复制代码
int main(int argc, char const *argv[])
{
    struct sequent_stack *s;
    s = stack_init(10);

    int n;
    scanf("%d",&n);

    while(n>0)
    {
        push(s,n%8);
        n /= 8;
    }

    int m;
    while(!stack_empty(s))
    {
        pop(s,&m);
        printf("%d",m);
    }

    printf("\n");

    return 0;
}

链式栈

对于链式栈来说以上那些基本操作也是需要实现的,由此我们进行

初始化

首先定义管理结构体和节点结构体

cpp 复制代码
struct node //栈节点结构体
{
    int data;
    struct node *next;
};

struct linked_stack //管理结构体
{
    int size;
    struct node *top;   //指向栈顶节点
};

再根据管理结构体进行初始化

cpp 复制代码
struct linked_stack *init_stack (void)
{
    struct linked_stack *s;
    s = malloc(sizeof(struct linked_stack));

    if(s != NULL)
    {
        s->size = 0;
        s->top = NULL;
    }

    return s;
}

压栈

cpp 复制代码
//创建新节点
struct node *new_node(int data)
{
    struct node *new;
    new = malloc(sizeof(struct node));

    if(s != NULL)
    {
        new->data = data;
        new->next = NULL;
    }

    return new;
}

//压栈
bool push(struct linked_stack *s,struct node *new)
{
    if (s == NULL || new == NULL)
        return false;
    
    new->next = s->top;
    s->top = new;
    s->size++;

    return true;
}

出栈

cpp 复制代码
bool stack_empty(struct linked_stack *s)
{
    return s->size == 0;
}

bool pop(struct linked_stack *s,int *p)
{
    if(s == NULL || p == NULL || stack_empty(s))
        return false;

    *p = s->top->data;
    s->top = s->top->next;
    s->size--;

    return true;
}

汉诺塔

根据链栈,写出一个汉诺塔问题的递归函数

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

struct node //栈节点结构体
{
    int data;
    struct node *next;
};

struct linked_stack //管理结构体
{
    int size;
    struct node *top;   //指向栈顶节点
};

struct linked_stack *init_stack (void)
{
    struct linked_stack *s;
    s = malloc(sizeof(struct linked_stack));

    if(s != NULL)
    {
        s->size = 0;
        s->top = NULL;
    }

    return s;
}

//创建新节点
struct node *new_node(int data)
{
    struct node *new;
    new = malloc(sizeof(struct node));

    if(new != NULL)
    {
        new->data = data;
        new->next = NULL;
    }

    return new;
}

//压栈
bool push(struct linked_stack *s,struct node *new)
{
    if (s == NULL || new == NULL)
        return false;
    
    new->next = s->top;
    s->top = new;
    s->size++;

    return true;
}

bool stack_empty(struct linked_stack *s)
{
    return s->size == 0;
}

bool pop(struct linked_stack *s,struct node **p)
{
    if(s == NULL || p == NULL || stack_empty(s))
        return false;

    *p = s->top;
    s->top = s->top->next;
    (*p)->next = NULL;
    s->size--;

    return true;
}

void show(struct linked_stack *A,struct linked_stack *B,struct linked_stack *C)
{
    int maxlen,len;

    maxlen = A->size > B->size ? A->size : B->size;
    maxlen = maxlen > C->size ? maxlen : C->size;
    len = maxlen;

    struct node *t1 = A->top;
    struct node *t2 = B->top;
    struct node *t3 = C->top;

    int i;
    for (i = 0; i < maxlen; i++)
    {
        if(t1 != NULL && len <= A->size)
        {
            printf("%d",t1->data);
            t1 = t1->next;
        }
        printf("\t");

        if(t2 != NULL && len <= B->size)
        {
            printf("%d",t2->data);
            t2 = t2->next;
        }
        printf("\t");

        if(t3 != NULL && len <= C->size)
        {
            printf("%d",t3->data);
            t3 = t3->next;
        }
        printf("\t");

        printf("\n");
        len--;
    }
    printf("A\tB\tC\n");
    printf("-----------------\n");
}

void hano(struct linked_stack *A,struct linked_stack *B,struct linked_stack *C,int n)
{
    if(n <= 0)
        return;
    
    struct node *tmp;
    hano(A,C,B,n-1);    //将n-1块从A借助C移向B

    getchar();          //每回车一次进行一步
    show(A,B,C);

    pop(A,&tmp);
    push(C,tmp);        //将A最下面一块移动到C

    hano(B,A,C,n-1);    //将n-1块从B借助A移向C
}

int main(int argc, char const *argv[])
{
    struct linked_stack *A = init_stack();
    struct linked_stack *B = init_stack();
    struct linked_stack *C = init_stack();

    int hanois = 0;
    scanf("%d",&hanois);

    int i;
    for (i = 0; i < hanois; i++)
    {
        struct node *new = new_node(hanois-i);  //将汉诺塔中的块放入栈A(柱A)
        push(A,new);
    }
    
    hano(A,B,C,hanois);

    show(A,B,C);

    return 0;
}
相关推荐
周杰伦_Jay29 分钟前
【Java虚拟机(JVM)全面解析】从原理到面试实战、JVM故障处理、类加载、内存区域、垃圾回收
java·jvm
摇滚侠1 小时前
Spring Boot 3零基础教程,IOC容器中组件的注册,笔记08
spring boot·笔记·后端
bnsarocket3 小时前
Verilog和FPGA的自学笔记2——点亮LED
笔记·fpga开发·verilog·自学
rit84324993 小时前
基于MATLAB的模糊图像复原
开发语言·matlab
fie88894 小时前
基于MATLAB的声呐图像特征提取与显示
开发语言·人工智能
程序员小凯4 小时前
Spring Boot测试框架详解
java·spring boot·后端
豐儀麟阁贵4 小时前
基本数据类型
java·算法
_extraordinary_5 小时前
Java SpringMVC(二) --- 响应,综合性练习
java·开发语言
程序员 Harry5 小时前
深度解析:使用ZIP流式读取大型PPTX文件的最佳实践
java
Larry_Yanan5 小时前
QML学习笔记(三十四)QML的GroupBox、RadioButton
c++·笔记·qt·学习·ui