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;
}
相关推荐
I_Am_Me_3 分钟前
【JavaEE进阶】 JavaScript
开发语言·javascript·ecmascript
重生之我是数学王子13 分钟前
QT基础 编码问题 定时器 事件 绘图事件 keyPressEvent QT5.12.3环境 C++实现
开发语言·c++·qt
xmh-sxh-131414 分钟前
jdk各个版本介绍
java
Ai 编码助手15 分钟前
使用php和Xunsearch提升音乐网站的歌曲搜索效果
开发语言·php
学习前端的小z19 分钟前
【前端】深入理解 JavaScript 逻辑运算符的优先级与短路求值机制
开发语言·前端·javascript
神仙别闹27 分钟前
基于C#和Sql Server 2008实现的(WinForm)订单生成系统
开发语言·c#
XINGTECODE28 分钟前
海盗王集成网关和商城服务端功能golang版
开发语言·后端·golang
天天扭码33 分钟前
五天SpringCloud计划——DAY2之单体架构和微服务架构的选择和转换原则
java·spring cloud·微服务·架构
程序猿进阶34 分钟前
堆外内存泄露排查经历
java·jvm·后端·面试·性能优化·oom·内存泄露
FIN技术铺38 分钟前
Spring Boot框架Starter组件整理
java·spring boot·后端