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;
}
相关推荐
程序猿进阶23 分钟前
ThreadLocal 释放的方式有哪些
java·开发语言·性能优化·架构·线程池·并发编程·threadlocal
战族狼魂25 分钟前
java代码 识别pdf文件是否含有表格
java·python·pdf
程序者王大川28 分钟前
【大数据】如何读取多个Excel文件并计算列数据的最大求和值
开发语言·python·excel·big data
Mryan200530 分钟前
OpenJudge | 寻找中位数
开发语言·数据结构·c++·算法·openjudge
码里法1 小时前
springmvc用配置类替换xml配置
java·spring·mvc
lizi888881 小时前
打包Python代码的常用方法实现程序exe应用
开发语言·python
api茶飘香2 小时前
守护应用边界:通过反射API实现安全的输入输出过滤
java·开发语言·python·安全·django·virtualenv·pygame
杀死一只知更鸟debug2 小时前
策略模式的小记
java·开发语言·策略模式
nice666602 小时前
CSS的基本语法
java·前端·css·visual studio code
efls1112 小时前
Qt_了解Qt Creator
开发语言·qt