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;
}
相关推荐
使者大牙几秒前
【大语言模型学习笔记】第一篇:LLM大规模语言模型介绍
笔记·学习·语言模型
IT技术分享社区9 分钟前
C#实战:使用腾讯云识别服务轻松提取火车票信息
开发语言·c#·云计算·腾讯云·共识算法
极客代码12 分钟前
【Python TensorFlow】入门到精通
开发语言·人工智能·python·深度学习·tensorflow
ssf-yasuo13 分钟前
SPIRE: Semantic Prompt-Driven Image Restoration 论文阅读笔记
论文阅读·笔记·prompt
疯一样的码农19 分钟前
Python 正则表达式(RegEx)
开发语言·python·正则表达式
代码之光_198020 分钟前
保障性住房管理:SpringBoot技术优势分析
java·spring boot·后端
ajsbxi25 分钟前
苍穹外卖学习记录
java·笔记·后端·学习·nginx·spring·servlet
&岁月不待人&41 分钟前
Kotlin by lazy和lateinit的使用及区别
android·开发语言·kotlin
StayInLove44 分钟前
G1垃圾回收器日志详解
java·开发语言
TeYiToKu1 小时前
笔记整理—linux驱动开发部分(9)framebuffer驱动框架
linux·c语言·arm开发·驱动开发·笔记·嵌入式硬件·arm