Day17、链式存储结构动态分配内存、栈的顺序存储结构和链式存储结构

这篇博客探讨了链式存储结构动态内存分配和释放,以及栈的顺序和链式存储结构。通过示例代码展示了如何在C语言中实现链表动态插入和释放内存,以及顺序栈的初始化、入栈、出栈等操作。此外,还提供了栈的链式存储结构的实现,并给出了简单的算术表达式计算的栈应用实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

复习:数组、指针和数组指针的关系

数组是一串连续的存储空间,数组名对应的是存储空间的首地址,比较安全、

指针有多样性,不安全,但是灵活,容易出现野指针

数组指针的本质是数组,数组里的元素是指针

 ---------------------------------------------------------------------------------------------------------------------------------

 

链式物理结构的动态分配内存、释放

链式物理结构中每个有效结点都应该是动态分配的

链式物理结构中能容纳的数字数量可以灵活变化

 

#include <stdio.h>

#include <stdlib.h>

typedef struct node

{

   int num;

   struct node *p_next;

} node;

int main()

{

   int num = 0;

   node head = {0},tail = {0},*p_tmp = NULL,*p_node = NULL;

   head.p_next = &tail;

   while (1)

    {

       printf("请输入一个数字:");

       scanf("%d",&num);

       if (num < 0)

       {

           break;

 

        }

       p_tmp = malloc(sizeof(node));

       if (!p_tmp)

       {

           continue;

       }

       p_tmp->num = num;

       p_tmp->p_next = NULL;

       for (p_node = &head;p_node != &tail;p_node = p_node->p_next)

       {

           node *p_first = p_node;

           node *p_mid = p_first->p_next;

           node *p_last = p_mid->p_next;

           if (p_mid == &tail)    //插在最后的位置

           {

                p_first->p_next = p_tmp;

                p_tmp->p_next = p_mid;

                break;

           }

       }

    }

   for (p_node = &head;p_node != &tail;p_node = p_node->p_next)

       {

           node *p_first = p_node;

           node *p_mid = p_first->p_next;

           node *p_last = p_mid->p_next;

           if (p_mid != &tail)

           {

                printf("%d",p_mid->num);

           }

       }

       printf("\n");

   

   

释放内存    while (head.p_next != &tail)   // 只要存在有效节点,循环就继续    

    {

           node *p_first = &head;

           node *p_mid = p_first->p_next;

           node *p_last = p_mid->p_next;

           p_first->p_next = p_last; // 先摘出来再释放

           free(p_mid);

           p_mid = NULL;

    }

return 0;

删除一个点时要释放内存:

#include <stdio.h>

#include <stdlib.h>

typedef struct node

{

   int num;

   struct node *p_next;

} node;

int main()

{

   int num = 0;

   node head = {0},tail = {0},*p_tmp = NULL,*p_node = NULL;

   head.p_next = &tail;

   while (1)

    {

       printf("请输入一个数字:");

       scanf("%d",&num);

       if (num < 0)

       {

           break;

 

       }

       p_tmp=(node *)malloc(sizeof(node));

       if (!p_tmp)

       {

           continue;

       }

        p_tmp->num = num;

       p_tmp->p_next = NULL;

       for (p_node = &head;p_node != &tail;p_node = p_node->p_next)

       {

           node *p_first = p_node;

           node *p_mid = p_first->p_next;

           node *p_last = p_mid->p_next;

            if (p_mid == &tail)

           {

                p_first->p_next = p_tmp;

                p_tmp->p_next = p_mid;

                break;

           }

       }

    }

   

   printf("请输入删除数字:");

   scanf("%d",&num);

   for (p_node = &head;p_node != &tail;p_node = p_node->p_next)

    {

       node *p_first = p_node;

       node *p_mid = p_first->p_next;

       node *p_last = p_mid->p_next;

       if (p_mid != &tail && p_mid->num == num)

       {

           p_first->p_next = p_last;   //先摘了,再释放

           free(p_mid);

           p_mid = NULL;

           break;

       }

    }

   

   for (p_node = &head;p_node != &tail;p_node = p_node->p_next)

       {

           node *p_first = p_node;

           node *p_mid = p_first->p_next;

           node *p_last = p_mid->p_next;

           if (p_mid != &tail)

           {

                printf("%d",p_mid->num);

           }

       }

       printf("\n");

 

   while (head.p_next != &tail)

    {

           node *p_first = &head;

           node *p_mid = p_first->p_next;

           node *p_last = p_mid->p_next;

           p_first->p_next = p_last;

           free(p_mid);

           p_mid = NULL;

    }

return 0;

 

 

 

栈是一种数据结构,栈里可以存放数字,数字有前后顺序,先放到栈里的数字在前面,后放到栈里的数字在后面

从栈里获得的数字一定是最后一个放进去的数字

这种使用数字的方法叫做后进先出

在实现入栈的时候需要提供一个push函数,它负责向栈里放一个数字

在实现出栈的时候需要提供一个pop函数,它负责从栈里获得一个数字

 

栈的顺序存储结构

准备工作

  1#include<stdio.h>

  2typedef struct{

 3     int buf[size];

 4     int qty;    //已经往数组(栈)里放了几个数

  5}stack;

  6//初始化函数

  7void stack_init(stack *p_stack){ //定义一个stack结构体类型的指针

 8     p_stack->qty=0;   //让栈里的数据为0

  9 }

 10//清理函数

 11void stack_deinit(stack *p_stack){//定义一个stack结构体类型的指针

 12    p_stack->qty=0;

 13 }

 14//判断栈是不是空函数

 15int stack_empty(const stack *p_stack){//加const关键字,不能改变指针所指向地址的内容,但可以改变地址的指向

 16    return !(p_stack->qty);

 17 }

 18//判断栈是不是满的

 19int stack_full(const stack *p_stack){

 20    return p_stack->qty==SIZE;

 21 }

 22//需要获得栈里的数字个数

23 int stack_size(const stack *p_stack){

 24    return p_stack->qty

 25 }

 26//向栈里放数字的函数

 27void stack_push(stack *p_stack,int num){

 28    p_stack->buf[p_stack->qty]=num;

 29    p_stack->qty++;

 30 }

 31//从栈里拿走最后一个数字

 32int stack_pop(stack *p_stack){

 33    p_stack->qty--;

 34    return p_stack->buf[p_stack->qty];

 35 }

 36//获得栈里最后一个数字

 37int stack_top(const stack *p_stack){

 38    return p_stack->buf[p_stack->qty-1];

 39 }

 

编写源函数

#include "02stack.h"

//初始化函数

void stack_init(stack *p_stack) {

   p_stack->qty = 0;

}

//清理函数

void stack_deinit(stack *p_stack) {

   p_stack->qty = 0;

}

//判断栈是不是空的函数

int stack_empty(const stack *p_stack) {

   return !(p_stack->qty);

}

//判断栈是不是满的函数

int stack_full(const stack *p_stack) {

   return p_stack->qty == SIZE;

}

//获得栈里的数字个数

int stack_size(const stack *p_stack) {

   return p_stack->qty;

}

//向栈里放数字的函数

void stack_push(stack *p_stack, int num) {

   p_stack->buf[p_stack->qty] = num;

   p_stack->qty++;

}

//从栈里拿走最后一个数字

int stack_pop(stack *p_stack) {

   p_stack->qty--;

   return p_stack->buf[p_stack->qty];

}

//获得栈里最后一个数字

int stack_top(const stack *p_stack) {

   return p_stack->buf[p_stack->qty - 1];

}

编写头文件:02stack.h

#ifndef    __02STACK_H__

#define    __02STACK_H__

typedef struct {

   int buf[SIZE];

   int qty;

} stack;

//初始化函数

void stack_init(stack *);

//清理函数

void stack_deinit(stack *);

//判断栈是不是空的函数

int stack_empty(const stack *);

//判断栈是不是满的函数

int stack_full(const stack *);

//获得栈里的数字个数

int stack_size(const stack *);

//向栈里放数字的函数

void stack_push(stack *, int );

//从栈里拿走最后一个数字

int stack_pop(stack *);

//获得栈里最后一个数字

int stack_top(const stack *);

#endif  //__02STACK_H__

 

编写主函数(测试用)

/*

    栈测试

*/

#include <stdio.h>

#include "02stack.h"

int main() {

   stack stk = {0};

   stack_init(&stk); 

   stack_push(&stk, 10);

   stack_push(&stk, 20);

   stack_push(&stk, 30);

   stack_push(&stk, 40);

   stack_push(&stk, 50);

   stack_push(&stk, 60);

   printf("数字个数是%d\n", stack_size(&stk));

   printf("判断满的结果是%d\n", stack_full(&stk));

   printf("%d ", stack_pop(&stk));

   printf("%d ", stack_pop(&stk));

   printf("%d ", stack_pop(&stk));

   printf("%d ", stack_pop(&stk));

   printf("%d ", stack_pop(&stk));

   printf("%d\n", stack_pop(&stk));

   stack_deinit(&stk);

   return 0;

}

输入指令  gcc –DSIZE=602main.c 02stack.c

 

栈的链式存储结构

 

编写源函数03stack.c

#include<stdlib.h>

#include"03stack.h"

//初始化函数

void stack_init(stack*p_stack) {   //定义一个stack结构体类型的指针

//头结点和尾结点连起来  就什么数据内容都没有

    p_stack->head.p_next =&(p_stack->tail);

    p_stack->tail.p_next = NULL;

}

//清理函数

void stack_deinit(stack*p_stack) { //定义一个stack结构体类型的指针

//把所有有效结点删除

    while (p_stack->head.p_next !=&(p_stack->tail)) {

        node *p_first =&(p_stack->head);

        node *p_mid = p_first->p_next;

        node *p_last = p_mid->p_next;

        p_first->p_next = p_last;

        free(p_mid);

        p_mid = NULL;

    }

}

//判断栈是不是空的函数

int stack_empty(conststack *p_stack) {

//如果头结点指针是尾结点地址就是空的

    return p_stack->head.p_next = =&(p_stack->tail);

}

//判断栈是不是满的函数

int stack_full(conststack *p_stack) {

    return 0;

}

//获得栈里的数字个数

int stack_size(conststack *p_stack) {

//进栈个数编号加一就是个数

    int cnt = 0;

    const node *p_node = NULL;

    for (p_node =&(p_stack->head);p_node != &(p_stack->tail);p_node =p_node->p_next) {

        const node *p_first = p_node;

        const node *p_mid = p_first->p_next;

        const node *p_last = p_mid->p_next;

        if (p_mid != &(p_stack->tail)) {

            cnt++;

        }

    }

    return cnt;

}

//向栈里放数字的函数

void stack_push(stack*p_stack, int num) {

    node *p_first = NULL, *p_mid = NULL, *p_last= NULL;

    node *p_tmp = (node *)malloc(sizeof(node));

    if (!p_tmp) {

        return ;

    }

    p_tmp->num = num;

    p_tmp->p_next = NULL;

    p_first = &(p_stack->head);

    p_mid = p_first->p_next;

    p_last = p_mid->p_next;

    p_first->p_next = p_tmp; //把数放在first和mid之间

    p_tmp->p_next = p_mid;

}

//从栈里拿走最后一个数字

int stack_pop(stack*p_stack) {

    int ret = 0;

    node *p_first = &(p_stack->head);

    node *p_mid = p_first->p_next;

    node *p_last = p_mid->p_next;

    p_first->p_next = p_last;

    ret = p_mid->num;

    free(p_mid);

    p_mid = NULL;

    return ret;

}

//获得栈里最后一个数字

int stack_top(conststack *p_stack) {

    return p_stack->head.p_next->num;

}

改写成头文件:03stack.h

#ifndef     __03STACK_H__

#define     __03STACK_H__

typedef struct node {

    int num;

    struct node *p_next;

} node;

typedef struct {

    node head, tail;

} stack;

//初始化函数

void stack_init(stack*);

//清理函数

void stack_deinit(stack*);

//判断栈是不是空的函数

int stack_empty(conststack *);

//判断栈是不是满的函数

int stack_full(conststack *);

//获得栈里的数字个数

int stack_size(conststack *);

//向栈里放数字的函数

void stack_push(stack*, int );

//从栈里拿走最后一个数字

int stack_pop(stack *);

//获得栈里最后一个数字

int stack_top(conststack *);

#endif   //__03STACK_H__

 

编写主函数:03main.c

/*

    栈测试

*/

#include<stdio.h>

#include "03stack.h"

int main() {

    stack stk = {0};

    stack_init(&stk);

    stack_push(&stk, 10);

    stack_push(&stk, 20);

    stack_push(&stk, 30);

    stack_push(&stk, 40);

    stack_push(&stk, 50);

    stack_push(&stk, 60);

    printf("数字个数是%d\n",stack_size(&stk));

    printf("判断满的结果是%d\n",stack_full(&stk));

    printf("%d ",stack_pop(&stk));

    printf("%d ",stack_pop(&stk));

    printf("%d ",stack_pop(&stk));

    printf("%d ",stack_pop(&stk));

    printf("%d ",stack_pop(&stk));

    printf("%d\n", stack_pop(&stk));

    stack_deinit(&stk);

    return 0;

}

输入指令:  gcc –DSIZE=6 03main.c 03stack.c

 

栈练习:

3*4+2-6/3:

#include <stdio.h>

#include "02stack.h"

int main() {

   int num = 0, num1 = 0, opr = 0;

   stack stk = {0};

   char buf[50] = {0}, *p_ch = buf;

    printf("请输入一个公式:");

   fgets(buf, 50, stdin);

   stack_init(&stk);

   while (1) {

       if (*p_ch >= '0' && *p_ch <= '9') {

           stack_push(&stk, *p_ch - '0');

       }

       else if (*p_ch == '*' || *p_ch == '/') {

           num = stack_pop(&stk);

           num1 = *(p_ch + 1) - '0';

           if (*p_ch == '*') {

                stack_push(&stk, num *num1);

           }

           else {

                stack_push(&stk, num /num1);

           }

           p_ch++;

       }

       else if (*p_ch == '+' || *p_ch== '-') {

           if (stack_size(&stk) == 3) {

                num1 = stack_pop(&stk);

                opr = stack_pop(&stk);

                num = stack_pop(&stk);

                if (opr == '+') {

                    stack_push(&stk, num +num1);

                }

                else {

                    stack_push(&stk, num -num1);

                }

           }

           stack_push(&stk, *p_ch);

       }

       else {

           if (stack_size(&stk) == 3) {

                num1 = stack_pop(&stk);

                opr = stack_pop(&stk);

                num = stack_pop(&stk);

                if (opr == '+') {

                    printf("计算结果是%d\n", num + num1);

                }

                else {

                   printf("计算结果是%d\n", num - num1);

                }

           }

           else {

                printf("计算结果是%d\n",stack_pop(&stk));

           }

           break;

       }

       p_ch++;

    }

   stack_deinit(&stk);

   return 0;

}

输入指令:gcc-DSIZE=10 04operand.c 02stack.c

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值