数据结构学习——4

一、栈

1.相关概念

栈定义:栈也是线性结构的一种,第一个进入栈的叫栈底(某些情况也是栈顶),特点是先进后出 LIFO

顺序栈:顺序表实现栈

链式栈:单链表实现栈

递增栈:栈底为低地址,栈顶为高地址(地址递增)

递减栈:栈底为高地址,栈顶为低地址(地址递减)

栈顶指针 top:指向栈顶的指针

空(top)递增/递减:top所指为栈顶元素的更顶上一个空的位置,入栈时先入再更改top。

满(top)递增/递减:top所指为栈顶元素,入栈时先更改top再将元素入栈。

顺序栈结构

typedef int data_t;
typedef struct{
    data_t data[20];
    int top;
}stack_t;

2.代码实现

stack.h

/*===============================================
*   文件名称:stack.h
*   创 建 者:     
*   创建日期:2025年07月30日
*   描    述:
================================================*/
#ifndef __STACK_H__
#define __STACK_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define LEN 20
typedef int data_t;
typedef struct
{
    data_t data[LEN];
    int top;
}stack_t;

//create
stack_t *stack_create();
//empty
int is_empty(stack_t *s);
//full
int is_full(stack_t *s);
//length
int get_length(stack_t *s);
//push
int stack_push(stack_t *s,data_t data);
//pop
data_t stack_pop(stack_t *s);
//show
void stack_show(stack_t *s);
//get_top
data_t get_top(stack_t *s);
//clear
void stack_clear(stack_t *s);
#endif

stack.c

/*===============================================
*   文件名称:stack.c
*   创 建 者:青木莲华
*   创建日期:2025年07月30日
*   描    述:满递增栈
================================================*/
#include "stack.h"

//create
stack_t *stack_create()
{
    stack_t *s = (stack_t *)malloc(sizeof(stack_t));
    if(s == NULL)
        return NULL;
    s->top = -1;
    return s;
}
//empty
int is_empty(stack_t *s)
{
    if(s == NULL)
        return 0;
    return s->top == -1;
}
//full
int is_full(stack_t *s)
{
    if(s == NULL)
        return 0;
    return s->top + 1 == LEN;
}
//length
int get_length(stack_t *s)
{
    if(s == NULL)
        return 0;
    return s->top + 1;
}
//push
int stack_push(stack_t *s,data_t data)
{
    if(s == NULL)
        return 0;
    if(is_full(s))
        return 0;

    s->top += 1;
    s->data[s->top] = data;
}
//pop
data_t stack_pop(stack_t *s)
{
    if(s == NULL)
        return 0;
    if(is_empty(s))
        return 0;
    s->top -= 1;
    return s->data[s->top + 1];
}
//show
void stack_show(stack_t *s)
{
    if(s == NULL)
        return;
    if(is_empty(s))
    {
        printf("栈为空!\n");
        return;
    }
    for(int i = 0 ; i <= s->top ; i++)
        printf("%4d ",s->data[i]);
    printf("\n");
}
//get top
int get_top(stack_t *s)
{
    if(s == NULL)
        return -1;
    if(is_empty(s))
        return -1;
    return s->top;
}
//clear
void stack_clear(stack_t *s)
{
    if(s == NULL)
        return;
    s->top = -1;
}

main.c

int main(int argc, char *argv[])
{ 
    stack_t *s = stack_create();
    if(s == NULL)
        return 0;
    for(int i = 1 ; i <= 10 ; i++)
        stack_push(s,i);
    stack_show(s);

    printf("出栈: %4d \n",stack_pop(s));
    printf("出栈: %4d \n",stack_pop(s));
    printf("出栈: %4d \n",stack_pop(s));
    printf("出栈: %4d \n",stack_pop(s));

    stack_show(s);
    //栈顶元素获取
    int top = get_top(s);
    if(top >= 0)
        printf("栈顶:%4d \n",s->data[top]);
    stack_clear(s);
    stack_show(s);
    return 0;
} 

二、链式栈(单链表)

使用单链表的形式,用head来表示top,所有Push都在top位置

stack.h

/*===============================================
*   文件名称:stack.h
*   创 建 者:青木莲华     
*   创建日期:2025年07月30日
*   描    述:栈 by 链表
================================================*/
#ifndef __STACK_H__
#define __STACK_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>



typedef int data_t;
typedef struct Node
{
    data_t data;
    struct Node *next;
}stack_t;

//create
stack_t *stack_create();
//empty
int is_empty(stack_t *s);
//length
int stack_length(stack_t *s);
//push
int stack_push(stack_t *s,data_t data);
//pop
data_t stack_pop(stack_t *s);
//show
void stack_show(stack_t *s);
#endif

stack.c

/*===============================================
*   文件名称:stack.c
*   创 建 者:青木莲华     
*   创建日期:2025年07月30日
*   描    述:栈 by 链表
================================================*/
#include "stack.h"

//create
stack_t *stack_create()
{
    stack_t *top = (stack_t *)malloc(sizeof(stack_t));
    if(top == NULL)
        return NULL;
    top->next = NULL;
    return top;
}
//empty
int is_empty(stack_t *top)
{
    return top->next == NULL;
}
//length
int stack_length(stack_t *top)
{
    int count = 0;
    if(is_empty(top))
        return count;
    stack_t *p = top->next;
    while(p != NULL)
    {
        count++;
        p = p->next;
    }
    return count;
}
//push
int stack_push(stack_t *top,data_t data)
{
    stack_t *new = (stack_t *)malloc(sizeof(stack_t));
    if(new == NULL)
        return 0;
    new->data = data;
    new->next = top->next;
    top->next = new;
    return 1;
}

//pop
data_t stack_pop(stack_t *top)
{
    if(is_empty(top))
        return -1;
    stack_t *p = top->next;
    top->next = p->next;
    data_t data = p->data;
    free(p);
    return data;
}
//show
void stack_show(stack_t *top)
{
    if(is_empty(top))
    {
        printf("栈为空!");
        return;
    }
    stack_t *p = top->next;
    while(p != NULL)
    {
        printf("%4d ",p->data);
        p = p->next;
    }
    printf("\n");
}

main.c

/*===============================================
*   文件名称:main.c
*   创 建 者:青木莲华
*   创建日期:2025年07月30日
*   描    述:栈 by 链表
================================================*/
#include "stack.h"

int main(int argc, char *argv[])
{ 
    stack_t *top = stack_create();
    if(top == NULL)
        return 0;
    for(int i = 1 ; i <= 10 ; i++)
        stack_push(top,i);

    stack_show(top);
    
    printf("pop : %4d\n",stack_pop(top));
    
    printf("pop : %4d\n",stack_pop(top));
    printf("pop : %4d\n",stack_pop(top));
    printf("pop : %4d\n",stack_pop(top));

    stack_show(top);
    return 0;
} 

三、循环队列

1.相关概念

定义:也是线性表,先进队的先出去,后进的后出

顺序队列:顺序表构成的队列

链式队列:链表构成的队列

队头指针:指向队头元素

队尾指针:指向队尾元素

注意:循环队列一定要有一个空间作为缓冲区(不使用)

2.代码实现

queue.h

/*===============================================
*   文件名称:queue.h
*   创 建 者:青木莲华     
*   创建日期:2025年07月30日
*   描    述:循环队列 by 数组
================================================*/

#ifndef __QUEUE_H__
#define __QUEUE_H__

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef int data_t;
typedef struct
{
    data_t *data;
    int front,rear;
    int len;
}queue_t;

//create
queue_t *queue_create(int size);
//empty
int is_empty(queue_t *q);
//full
int is_full(queue_t *q);
//length
int queue_length(queue_t *q);
//en
int queue_en(queue_t *q,data_t data);
//de
data_t queue_de(queue_t *q);
//show
void queue_show(queue_t *q);


#endif

queue.c

/*===============================================
*   文件名称:queue.c
*   创 建 者:青木莲华
*   创建日期:2025年07月30日
*   描    述:循环队列 by 数组
================================================*/

#include "queue.h"

//create
queue_t *queue_create(int size)
{
    queue_t *q = (queue_t *)malloc(sizeof(queue_t));
    if(q == NULL)
        return NULL;
    q->data = (data_t *)malloc(sizeof(data_t) * size);
    if(q->data == NULL)
        return NULL;
    q->front = q->rear = size - 1;
    q->len = size;
    return q;
}
//empty
int is_empty(queue_t *q)
{
    return q->front == q->rear;
}
//full
int is_full(queue_t *q)
{
   return (q->rear + 1) % q->len == q->front; 
}
//length
int queue_length(queue_t *q)
{
    
    return (q->rear - q->front + q->len) % q->len;
}
//en
int queue_en(queue_t *q,data_t data)
{
    if(is_full(q)) 
        return 0;
    q->rear = (q->rear + 1) % q->len;
    q->data[q->rear] = data;
    return 1;
}
//de
data_t queue_de(queue_t *q)
{
    if(is_empty(q))
    {    
        return 0;
    }
    q->front = (q->front + 1) % q->len;
    return q->data[q->front];
}

//show
void queue_show(queue_t *q)
{
    if(is_empty(q))
    {
        printf("队已空!\n");
        return;
    }
    int i;
    for(i = (q->front+1)%q->len ;
        i != (q->rear+1)%q->len ;
        i = (i + 1) % q->len)
    {
        printf("%4d ",q->data[i]);
    }
    printf("\n");
}

main.c

/*===============================================
*   文件名称:main.c
*   创 建 者:青木莲华 
*   创建日期:2025年07月30日
*   描    述:循环队列 by 数组
================================================*/
#include "queue.h"

int main(int argc, char *argv[])
{ 
    int len = 10;
    queue_t *q = queue_create(len);
    int i = 1;
    while(i < 15)
    {
        if(is_full(q))
            break;
        queue_en(q,i);
        i++;
    }
    queue_show(q);
     
    printf("out : %d\n",queue_de(q));
    printf("out : %d\n",queue_de(q));
    printf("out : %d\n",queue_de(q));
    printf("out : %d\n",queue_de(q));
    printf("out : %d\n",queue_de(q));

    queue_show(q);
    queue_en(q,11);
    queue_en(q,22);
    queue_en(q,33);
    queue_show(q);
    return 0;
} 

运行截图

alt

四、作业

用非循环 单链表实现排序操作

选择排序函数(单链表详细代码参考之前笔记)

/*===============================================
*   文件名称:link.c
*   创 建 者:青木莲华     
*   创建日期:2025年07月28日
*   描    述:非循环单链表 选择排序
================================================*/
//排序 sort   用选择排序实现
void link_sort(link_t *head)
{
    link_t *p = head;               //每次比较确定的最小值节点所在位置,下一趟最小值前驱
    link_t *q = head->next;         //遍历用指针
    link_t *mp = p;                 //最小节点前驱
    link_t *min = head->next;       //最小节点
    int len = link_length(head);    //链表节点个数,循环趟数为 len - 1次
    
    for(int i = 1 ; i < len ; i++)
    {

        while(q->next != NULL)      //min 与 q->next 比较 所以循环条件为q->next != NULL
        {
            if(min->data > q->next->data)   //min节点大于q节点则 mp = q , min = q->next;
            {
                mp = q;
                min = q->next;
            }
            q = q->next;
        }
        mp->next = min->next;       //改变最小节点的前驱后继的指向,保证链表不断
                                    //将min插入到p->next位置(更改本次循环最小节点位置)
        min->next = p->next;
        p->next = min;

        p = p->next;                //重置p位置到当前最小节点位置
        mp = p;                     //重置最小节点前驱                     
        min = p->next;              
        q = p->next;
    }
}

main.c

/*===============================================
*   文件名称:main.c
*   创 建 者:青木莲华     
*   创建日期:2025年07月28日
*   描    述:非循环单链表 选择排序
================================================*/
#include "link.h"

int main(int argc, char *argv[])
{ 
    link_t *head = link_create();
    if(head == NULL)
        printf("create failed\n");
    
    link_insert(head,7,0);
    link_insert(head,13,0);
    link_insert(head,55,0);
    link_insert(head,11,0);
    link_insert(head,8,0);
    
    link_show(head);

    //排序
    link_sort(head);
    link_show(head);
    return 0;
} 

运行截图

alt