C语言强化学习第一天(栈与队列)

本文介绍了数据结构中的栈和队列的基本概念、逻辑结构和物理结构。通过C语言代码展示了栈和队列的实现,包括栈的后进先出特性、队列的先进先出特性,并提供了完整的压栈、弹栈、入队、出队等操作。此外,还提及了栈在操作系统中的应用,如鸡尾酒调制和函数调用,以及队列在Linux系统中的消息队列、工作队列和等待队列的应用。
摘要由CSDN通过智能技术生成

英文:
top:头部,顶部
capacity:容量,大小
stack:栈
init = initialization:初始化
full:满
empty:空
push:压入
pop:弹出
queue:队列

1.结构体的专项训练:
1.1.结构体数组

/*结构体数组*/
#include <stdio.h>
//求数组元素个数
#define ARRYA_SIZE(x) (sizeof(x)/sizeof(x[0]))
/*声明描述学生信息的结构体*/
typedef struct student {
    char name[30]; //姓名
    int age; //年龄
    int sex; //性别
}stu_t;
int main(void)
{
    /*1.定义两个学生信息的结构体变量*/
    //stu_t info[] = {{"关羽", 18, 1}, {"黄蓉", 16, 0}};
    stu_t info[] = {
        {
            .sex = 1,
            .age = 18,
            .name = "关羽"
        },
        {
            .sex = 0,
            .age = 16,
            .name = "黄蓉"
        }
    };
    for(int i = 0; i < ARRYA_SIZE(info); i++)
        printf("%s %d %d\n", info[i].name, info[i].age, info[i].sex);
    info[0].age++;
    info[1].age++;
    for(int i = 0; i < ARRYA_SIZE(info); i++)
        printf("%s %d %d\n", info[i].name, info[i].age, info[i].sex);
    return 0;
}

1.2.结构体和函数指针组合

/*结构体和函数指针*/
#include <stdio.h>
//此声明告诉gcc stu_t声明在下面,前面需要用到
typedef struct student stu_t;
//声明函数指针数据类型
typedef void (*pfunc_t)(stu_t *);
//声明结构体
typedef struct student {
    char name[30]; //姓名 
    int age; //年龄
    int sex; //性别
    pfunc_t pfunc1; //函数指针变量将来指向一个操作函数
    pfunc_t pfunc2; //函数指针变量将来指向一个操作函数
}stu_t;
//定义打印学生信息函数show和grow
void show(stu_t *pstu){
    printf("%s %d %d\n", pstu->name, pstu->age, pstu->sex);
}
void grow(stu_t *pstu) {
    pstu->age++;
}
int main(void)
{
    //定义结构体变量描述学生信息
    stu_t  student1 = {
        .name = "刘备",
        .age = 19,
        .sex = 1,
        .pfunc1 = show, //指向show函数
        .pfunc2 = grow //指向grow函数
    };
    //调用student1学生的操作函数show和grow
    student1.pfunc1(&student1);//执行pfunc1 show
    student1.pfunc2(&student1);//执行pfunc2 grow
    student1.pfunc1(&student1);//执行pfunc1 show
    return 0;
}


第二阶段课程内容:数据结构和算法
数据结构:栈,队列,单链表,双链表,二叉树
算法:2个查找算法,5个排序算法
1.基本概念
数据结构:描述计算机中数据之间的关系和存储方式

2.数据结构分类
a)逻辑结构:描述数据之间的关系
b)物理结构:描述数据的存放方式
c)运算结构:描述数据的运算过程,例如:+,-等

3.逻辑结构
a)集合结构:强调总体,不强调数据之间的关系
例如:CSD1911班级就是一个集合结构,同学之间无关系
2,3,5,7…统称为素数
b)线性结构:描述数据一对一的前后关系
例如:排队打饭,公交车排队
c)树形结构:描述数据的一对多的关系
例如:树,家谱
d)网状结构:数据的多对多的关系
例如:蜘蛛网,网球拍

4.物理结构
a)顺序存储结构
采用数组来存储数据
b)链式存储结构
采用链表:单链表和双链表

5.结论:数据结构重点掌握:栈,队列,单链表,双链表,有序二叉树

6.数据结构之栈(又称堆栈)
a)栈的基本特性
具有后进先出的特性(Last In First Out=LIFO)
或者
具有先进后出的特性(First In Last Out=FILO)
例如:放书和取书,鸡尾酒
栈的操作只能操作栈顶!
入栈又称压栈
出栈又称弹栈

b)栈的操作基本原理
在这里插入图片描述

/*栈演示代码*/
#include <stdio.h>
#include <stdlib.h> //为了用malloc函数
/*声明描述栈属性信息的结构体*/
typedef struct stack {
    int *arr; //数组的首地址
    int cap; //栈的容量大小
    int top; //栈顶
}stack_t;
/*定义栈相关的操作函数*/
//1.给栈分配内存,让arr指向分配的内存的首地址
//并且把栈初始化为空栈(没有数据)
void stack_init(stack_t *stack, int cap)
{
    //分配内存,让arr指向分配的内存
    stack->arr = (int *)malloc(cap * sizeof(int));
    stack->cap = cap; //指定栈容量
    stack->top = 0; //空栈
}
//2.释放内存并且恢复到初始化状态
void stack_deinit(stack_t *stack) 
{
    free(stack->arr);
    stack->cap = 0;
    stack->top = 0;
}
//3.判断是否满
int stack_full(stack_t *stack)
{
    //栈顶top大于等于容量cap,就是满
    return stack->top >= stack->cap; //满返回1,不满返回0
}
//4.判断是否空
int stack_empty(stack_t *stack)
{
    return !stack->top; //空(top=0)返回1,不空返回0 
}
//5.入栈(压栈),向分配的内存中保存数据
//data:就是要保存的数据
void stack_push(stack_t *stack, int data)
{
    stack->arr[stack->top++] = data;
}
//6.出栈(弹栈),从栈中取出数据
int stack_pop(stack_t *stack)
{
    return stack->arr[--stack->top];
}
//7.仅仅获取栈顶元素(最上面的一个数字)
int stack_top(stack_t *stack)
{
    return stack->arr[stack->top-1];
}
//8.获取栈中目前保存数据的个数
int stack_size(stack_t *stack)
{
    return stack->top;
}
//测试主函数
int main(int argc, char *argv[])
{
    //1.定义栈
    stack_t stack; 

    //2.初始化栈,给栈分配存储数据的内存空间并且指定容量
    stack_init(&stack, 10);

    //3.判断空和满
    int ret = 0;
    ret = stack_full(&stack);
    printf("%s\n", ret ? "满":"不满");
    ret = stack_empty(&stack);
    printf("%s\n", ret ? "空":"不空");
   
    //4.压栈
    int i = 250;
    while(!stack_full(&stack)) {
        stack_push(&stack, i++);
    }
    ret = stack_full(&stack);
    printf("%s\n", ret ? "满":"不满");
    printf("栈顶的值是%d\n", stack_top(&stack));
    printf("栈的大小是%d\n", stack_size(&stack));

    //5.出栈
    while(!stack_empty(&stack)) {
        printf("%d ", stack_pop(&stack));
    }
    printf("\n");
    ret = stack_empty(&stack);
    printf("%s\n", ret ? "空":"不空");
    
    //6.释放内存
    stack_deinit(&stack);
    return 0;
}

7.数据结构之队列
a)特性:先进先出(First In First Out=FIFO),取数从队列的开头取,存储从队列尾部存
第一个元素又称首元素,最后一个元素又称尾元素
b)linux系统三大队列:
消息队列:进程间通信的一种手段
工作队列:延后执行的一种手段
等待队列:随时随地让进程休眠并且让进程随时随地被唤醒
在这里插入图片描述

/*队列*/
#include <stdio.h>
#include <stdlib.h>
/*声明描述队列属性的结构体*/
typedef struct queue {
    int *arr; //首地址
    int cap; //容量
    int size; //有效数据的个数
    int front; //前端(出队)
    int rear; //后端(入队)
}queue_t;
//1.定义分配内存和初始化队列函数
void queue_init(queue_t *queue, int cap)
{
    queue->arr = (int *)malloc(cap * sizeof(queue->arr[0]));//分配内存
    queue->cap = cap; //容量
    queue->size = 0; //无数
    queue->front = 0; 
    queue->rear = 0;
}
//2.释放内存并且恢复到初始状态
void queue_deinit(queue_t *queue)
{
    free(queue->arr);
    queue->cap = 0; 
    queue->size = 0; //无数
    queue->front = 0; 
    queue->rear = 0;

}
//3.判断是否满
int queue_full(queue_t *queue)
{
    return queue->size >= queue->cap; //满返回1,不满返回0
}
//4.判断是否空
int queue_empty(queue_t *queue)
{
    return !queue->size; //空返回1,不空返回0
}
//5.入队
void queue_push(queue_t *queue, int data)
{
    if(queue->rear >= queue->cap)
        queue->rear = 0; //如果队列的前面有空位置,重新定位rear,
                         //让队列变成一个循环队列
    queue->arr[queue->rear++] = data;
    queue->size++;
}
//6.出队
int queue_pop(queue_t *queue)
{
    if(queue->front >= queue->cap)
        queue->front = 0; //取到队尾,然后前面还有数据,重新定位front
    queue->size--;
    return queue->arr[queue->front++];
}
//7.获取有效数据的个数
int queue_size(queue_t *queue)
{
    return queue->size;
}
//8.获取队首元素的值
//测试主函数

int main(void)
{
    //1.定义队列
    queue_t queue;

    //2.初始化队列
    queue_init(&queue, 4);
    //3.入队:10 20 30 40
    for(int i = 10; i <= 40; i += 10) {
        if(!queue_full(&queue)) {
            queue_push(&queue, i);
        } 
    }
    //4.出队:10 20
    for(int i = 0; i < 2; i++) {
        if(!queue_empty(&queue)) {
            printf("%d ", queue_pop(&queue));
        }
    }
    printf("\n");
    //5.入队: 50 60 30 40
    for(int i = 50; i <= 60; i += 10) {
        if(!queue_full(&queue)) {
            queue_push(&queue, i);
        }
    }
    //6.整体出队
    while(!queue_empty(&queue)) {
        printf("%d ", queue_pop(&queue));
    }
    printf("\n");

    //7.销毁队列
    queue_deinit(&queue);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值