数据结构-链表、栈、动态数组、队列

数据结构

不透明指针

定义

不透明指针是指指向一个数据结构的指针,但该数据结构的内部细节对外部代码是不可见的。外部代码只能通过提供的接口函数来操作该数据结构,而无法直接访问其内部成员。

优点

  • 封装性:隐藏数据结构的内部实现细节,防止外部代码直接修改数据结构,提高代码的安全性和稳定性。
  • 模块化:将数据结构和操作函数分离,便于模块化设计和代码复用。
  • 可扩展性:可以在不修改外部代码的情况下,修改数据结构的内部实现,提高代码的可扩展性。

应用场景

不透明指针广泛应用于各种需要封装和模块化的场景,包括但不限于:

  • 库开发:在库中使用不透明指针,隐藏内部数据结构,只暴露必要的接口函数。
  • 数据结构实现:在实现复杂数据结构时,使用不透明指针隐藏内部细节,提高代码的可维护性。
  • 操作系统:在操作系统中使用不透明指针,隐藏内部数据结构,提高系统的安全性和稳定性。

不透明指针的实现

定义不透明指针类型

首先,定义一个不透明指针类型,通常使用 typedef 关键字。例如:

typedef struct _MyData MyData;

这里,MyData 是一个不透明指针类型,struct _MyData 的内部细节对外部代码是不可见的。

链表

知识点

链表由一系列的节点(Node)构成,每个节点包含数据和指向下一个节点的指针。链表的主要优点是插入和删除操作的时间复杂度为 O(1),但访问特定元素的时间复杂度为 O(n)。

节点(Node)

  1. 链表的基本单元是节点,每个节点包含两个部分:
  • 数据域:存储数据。
  • 指针域:指向下一个节点的指针。

由于我们不知道用户的数据是怎么存储的,所以我们可以,单独讲节点独立出来,仅仅保留指针域,该指针域将在用户的数据前四个字节。

头节点(Head)

链表的第一个节点称为头节点(Head)。头节点用于标识链表的起始位置。

尾节点(Tail)

链表的最后一个节点称为尾节点(Tail)。尾节点的指针域通常指向 NULL,表示链表的结束。

单向链表

#pragma once

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

// 定义链表的别名
typedef void* LinkList;
// 节点结构体设计
typedef struct LinkNode {
    // 维护指针域
    struct LinkNode* next;
} LinkNode_t;

// 初始化链表
LinkList init_LinkList(void);

// 插入节点
void insert_LinkList(LinkList list, int pos, void* data);

// 遍历链表
void foreach_LinkList(LinkList list, void (*myprint)(void*));

// 销毁链表
void destroy_LinkList(LinkList list);

// 根据位置删除节点
void removeByPos_LinkList(LinkList list, int pos);

// 根据值删除节点
void removeByValue_LinkList(LinkList list, void* data, int (*myCompare)(void*, void*));
#include "list.h"


// 链表结构体设计
typedef struct {
    LinkNode_t pHeader;  // 头节点
    int m_Size;          // 链表大小
} LinkList_t;

/**
 * @brief 初始化链表
 *
 * @return LinkList 返回初始化后的链表指针,如果内存分配失败则返回NULL
 */
LinkList init_LinkList(void) {
    // 分配链表结构体内存
    LinkList_t* mylist = malloc(sizeof(LinkList_t));
    if (mylist == NULL) {
        // 内存分配失败,返回NULL
        return NULL;
    }
    // 初始化链表属性
    mylist->m_Size = 0;
    mylist->pHeader.next = NULL;
    return mylist;
}

/**
 * @brief 插入节点
 *
 * @param list 链表指针
 * @param pos 插入位置
 * @param data 要插入的数据指针
 */
void insert_LinkList(LinkList list, int pos, void* data) {
    if (list == NULL || data == NULL) {
        // 链表或数据为空,直接返回
        return;
    }
    LinkList_t* mylist = (LinkList_t*)list;
    if (pos < 0 || pos > mylist->m_Size) {
        // 无效位置,默认插入到链表末尾
        pos = mylist->m_Size;
    }
    // 取出用户数据的前四个空间
    LinkNode_t* myNode = (LinkNode_t*)data;
    // 找到待插入数据位置
    LinkNode_t* pCurrent = &mylist->pHeader;
    for (int i = 0; i < pos; i++) {
        pCurrent = pCurrent->next;
    }
    // 更改指针指向
    myNode->next = pCurrent->next;
    pCurrent->next = myNode;
    // 更新链表大小
    mylist->m_Size++;
}

/**
 * @brief 遍历链表
 *
 * @param list 链表指针
 * @param myprint 打印函数指针
 */
void foreach_LinkList(LinkList list, void (*myprint)(void*)) {
    if (list == NULL || myprint == NULL) {
        // 链表或打印函数为空,直接返回
        return;
    }
    LinkList_t* myList = (LinkList_t*)list;
    LinkNode_t* pCurrent = myList->pHeader.next;
    for (int i = 0; i < myList->m_Size; i++) {
        // pCurrent就是用户数据首地址
        myprint(pCurrent);
        pCurrent = pCurrent->next;
    }
}

/**
 * @brief 销毁链表
 *
 * @param list 链表指针
 */
void destroy_LinkList(LinkList list) {
    if (list == NULL) {
        // 链表为空,直接返回
        return;
    }
    LinkList_t* myList = (LinkList_t*)list;
    LinkNode_t* pCurrent = myList->pHeader.next;
    while (pCurrent != NULL) {
        LinkNode_t* pNext = pCurrent->next;
        free(pCurrent);
        pCurrent = pNext;
    }
    // 释放链表结构体内存
    free(myList);
}

/**
 * @brief 根据位置删除节点
 *
 * @param list 链表指针
 * @param pos 删除位置
 */
void removeByPos_LinkList(LinkList list, int pos) {
    if (list == NULL) {
        // 链表为空,直接返回
        return;
    }
    LinkList_t* myList = (LinkList_t*)list;
    if (pos < 0 || pos >= myList->m_Size) {
        // 无效位置,直接返回
        return;
    }
    // 找到待删除节点的前驱节点
    LinkNode_t* pCurrent = &myList->pHeader;
    for (int i = 0; i < pos; i++) {
        pCurrent = pCurrent->next;
    }
    // 获取待删除节点
    LinkNode_t* pDel = pCurrent->next;
    // 建立节点之间的关系
    pCurrent->next = pDel->next;
    // 释放待删除节点的内存
    // free(pDel); pDel是用户的,我们没资格free
    // 更新链表大小
    myList->m_Size--;
}

/**
 * @brief 根据值删除节点
 *
 * @param list 链表指针
 * @param data 要删除的数据指针
 * @param myCompare 比较函数指针
 */
void removeByValue_LinkList(LinkList list, void* data, int (*myCompare)(void*, void*)) {
    if (list == NULL || data == NULL || myCompare == NULL) {
        // 链表、数据或比较函数为空,直接返回
        return;
    }
    LinkList_t* myList = (LinkList_t*)list;
    // 找到待删除节点的前驱节点
    LinkNode_t* pCurrent = &myList->pHeader;
    for (int i = 0; i < myList->m_Size; i++) {
        if (myCompare(pCurrent->next, data)) {
            // 找到匹配的节点
            LinkNode_t* pDel = pCurrent->next;
            // 建立节点之间的关系
            pCurrent->next = pDel->next;
            // 释放待删除节点的内存
            // free(pDel);
            // 更新链表大小
            myList->m_Size--;
            return;
        }
        pCurrent = pCurrent->next;
    }
}

双链表

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义链表的别名
typedef void* LinkList;

// 节点结构体设计
typedef struct LinkNode {
    struct LinkNode* prev; // 指向前一个节点的指针
    struct LinkNode* next; // 指向下一个节点的指针
} LinkNode_t;

// 链表结构体设计
typedef struct {
    LinkNode_t pHeader;  // 头节点
    int m_Size;          // 链表大小
} LinkList_t;

// 初始化链表
LinkList init_LinkList(void);

// 插入节点
void insert_LinkList(LinkList list, int pos, void* data);

// 遍历链表
void foreach_LinkList(LinkList list, void (*myprint)(void*));

// 销毁链表
void destroy_LinkList(LinkList list);

// 根据位置删除节点
void removeByPos_LinkList(LinkList list, int pos);

// 根据值删除节点
void removeByValue_LinkList(LinkList list, void* data, int (*myCompare)(void*, void*));
#include "list.h"

/**
 * @brief 初始化链表
 *
 * @return LinkList 返回初始化后的链表指针,如果内存分配失败则返回NULL
 */
LinkList init_LinkList(void) {
    LinkList_t* mylist = malloc(sizeof(LinkList_t));
    if (mylist == NULL) {
        return NULL;
    }
    mylist->m_Size = 0;
    mylist->pHeader.prev = &mylist->pHeader; // 头节点的 prev 指针指向自身
    mylist->pHeader.next = &mylist->pHeader; // 头节点的 next 指针指向自身
    return mylist;
}

/**
 * @brief 插入节点
 *
 * @param list 链表指针
 * @param pos 插入位置
 * @param data 要插入的数据指针
 */
void insert_LinkList(LinkList list, int pos, void* data) {
    if (list == NULL || data == NULL) {
        return;
    }
    LinkList_t* mylist = (LinkList_t*)list;
    if (pos < 0 || pos > mylist->m_Size) {
        pos = mylist->m_Size;
    }
    LinkNode_t* myNode = (LinkNode_t*)data;
    LinkNode_t* pCurrent = &mylist->pHeader;
    for (int i = 0; i < pos; i++) {
        pCurrent = pCurrent->next;
    }
    myNode->next = pCurrent->next;
    myNode->prev = pCurrent;
    pCurrent->next->prev = myNode; // 更新后继节点的前驱指针
    pCurrent->next = myNode;
    mylist->m_Size++;
}

/**
 * @brief 遍历链表
 *
 * @param list 链表指针
 * @param myprint 打印函数指针
 */
void foreach_LinkList(LinkList list, void (*myprint)(void*)) {
    if (list == NULL || myprint == NULL) {
        return;
    }
    LinkList_t* myList = (LinkList_t*)list;
    LinkNode_t* pCurrent = myList->pHeader.next;
    for (int i = 0; i < myList->m_Size; i++) {
        myprint(pCurrent);
        pCurrent = pCurrent->next;
    }
}

/**
 * @brief 销毁链表
 *
 * @param list 链表指针
 */
void destroy_LinkList(LinkList list) {
    if (list == NULL) {
        return;
    }
    LinkList_t* myList = (LinkList_t*)list;
    LinkNode_t* pCurrent = myList->pHeader.next;
    while (pCurrent != &myList->pHeader) { // 遍历到头节点为止
        LinkNode_t* pNext = pCurrent->next;
        free(pCurrent);
        pCurrent = pNext;
    }
    free(myList);
}

/**
 * @brief 根据位置删除节点
 *
 * @param list 链表指针
 * @param pos 删除位置
 */
void removeByPos_LinkList(LinkList list, int pos) {
    if (list == NULL) {
        return;
    }
    LinkList_t* myList = (LinkList_t*)list;
    if (pos < 0 || pos >= myList->m_Size) {
        return;
    }
    LinkNode_t* pCurrent = &myList->pHeader;
    for (int i = 0; i < pos; i++) {
        pCurrent = pCurrent->next;
    }
    LinkNode_t* pDel = pCurrent->next;
    pCurrent->next = pDel->next;
    pDel->next->prev = pCurrent; // 更新后继节点的前驱指针
    myList->m_Size--;
}

/**
 * @brief 根据值删除节点
 *
 * @param list 链表指针
 * @param data 要删除的数据指针
 * @param myCompare 比较函数指针
 */
void removeByValue_LinkList(LinkList list, void* data, int (*myCompare)(void*, void*)) {
    if (list == NULL || data == NULL || myCompare == NULL) {
        return;
    }
    LinkList_t* myList = (LinkList_t*)list;
    LinkNode_t* pCurrent = &myList->pHeader;
    for (int i = 0; i < myList->m_Size; i++) {
        if (myCompare(pCurrent->next, data)) {
            LinkNode_t* pDel = pCurrent->next;
            pCurrent->next = pDel->next;
            pDel->next->prev = pCurrent; // 更新后继节点的前驱指针
            myList->m_Size--;
            return;
        }
        pCurrent = pCurrent->next;
    }
}

动态数组

动态数组(Dynamic Array)是一种可以根据需要动态调整大小的数组。与静态数组不同,动态数组的大小在运行时可以改变,从而避免了静态数组固定大小的限制。动态数组通常通过在堆内存中分配空间来实现,可以使用指针和动态内存分配函数(如 mallocreallocfree)来管理内存。

#ifndef DYNAMICARRAY_H
#define DYNAMICARRAY_H

// 定义动态数组的别名
typedef void* DynamicArray;

// 初始化数组  返回值数组指针
DynamicArray init_dynamicArray(int capacity);

// 插入数组
void insert_dynamicArray(DynamicArray arr, void* data, int pos);

// 遍历
void foreach_dynamicArray(DynamicArray arr, void (*myPrint)(void*));

// 根据位置删除
void removeByPos_dynamicArray(DynamicArray arr, int pos);

// 根据值删除
void removeByValue_dynamicArray(DynamicArray arr, void* data, int (*myCompare)(void*, void*));

// 销毁数组
void destroy_dynamicArray(DynamicArray arr);

#endif // DYNAMICARRAY_H
#include "dynamicArray.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 动态数组结构体
typedef struct {
    // 真实在堆区开辟的数组的指针
    void** pAddr;
    // 数组容量
    int m_Capacity;
    // 数组大小
    int m_Size;
} dynamicArray_t;

/**
 * @brief 初始化数组
 *
 * @param capacity 数组的初始容量
 * @return DynamicArray 返回初始化后的数组指针,如果内存分配失败则返回NULL
 */
DynamicArray init_dynamicArray(int capacity) {
    if (capacity <= 0) {
        return NULL;
    }
    // 给数组分配内存
    dynamicArray_t* arr = malloc(sizeof(dynamicArray_t));
    if (arr == NULL) {
        return NULL;
    }
    // 给属性初始化
    arr->m_Capacity = capacity;
    arr->pAddr = malloc(sizeof(void*) * capacity);
    if (arr->pAddr == NULL) {
        free(arr);
        return NULL;
    }
    arr->m_Size = 0;
    return arr;
}

/**
 * @brief 插入数组
 *
 * @param arr 数组指针
 * @param data 要插入的数据指针
 * @param pos 插入位置
 */
void insert_dynamicArray(DynamicArray arr, void* data, int pos) {
    if (arr == NULL || data == NULL) {
        return;
    }
    dynamicArray_t* myArr = (dynamicArray_t*)arr;
    if (pos < 0 || pos > myArr->m_Size) {
        // 尾插
        pos = myArr->m_Size;
    }
    // 判断数组是否满了
    if (myArr->m_Size == myArr->m_Capacity) {
        int newCapacity = myArr->m_Capacity * 2;
        // 开辟新空间
        void** newSpace = malloc(sizeof(void*) * newCapacity);
        if (newSpace == NULL) {
            return;
        }
        // 将原空间内容拷贝到新空间下
        memcpy(newSpace, myArr->pAddr, myArr->m_Size * sizeof(void*));
        // 释放原空间
        free(myArr->pAddr);
        // 更改指针指向
        myArr->pAddr = newSpace;
        // 更新容量
        myArr->m_Capacity = newCapacity;
    }
    // 移动元素
    for (int i = myArr->m_Size - 1; i >= pos; i--) {
        myArr->pAddr[i + 1] = myArr->pAddr[i];
    }
    // 插入数据
    myArr->pAddr[pos] = data;
    myArr->m_Size++;
}

/**
 * @brief 遍历数组
 *
 * @param arr 数组指针
 * @param myPrint 打印函数指针
 */
void foreach_dynamicArray(DynamicArray arr, void (*myPrint)(void*)) {
    if (arr == NULL || myPrint == NULL) {
        return;
    }
    dynamicArray_t* myArr = (dynamicArray_t*)arr;
    for (int i = 0; i < myArr->m_Size; i++) {
        myPrint(myArr->pAddr[i]);
    }
}

/**
 * @brief 根据位置删除数组元素
 *
 * @param arr 数组指针
 * @param pos 删除位置
 */
void removeByPos_dynamicArray(DynamicArray arr, int pos) {
    if (arr == NULL) {
        return;
    }
    dynamicArray_t* myArr = (dynamicArray_t*)arr;
    if (pos < 0 || pos >= myArr->m_Size) {
        return;
    }
    // 删除指定位置,从前往后移动
    for (int i = pos; i < myArr->m_Size - 1; i++) {
        myArr->pAddr[i] = myArr->pAddr[i + 1];
    }
    myArr->m_Size--;
}

/**
 * @brief 根据值删除数组元素
 *
 * @param arr 数组指针
 * @param data 要删除的数据指针
 * @param myCompare 比较函数指针
 */
void removeByValue_dynamicArray(DynamicArray arr, void* data, int (*myCompare)(void*, void*)) {
    if (arr == NULL || data == NULL || myCompare == NULL) {
        return;
    }
    dynamicArray_t* myArr = (dynamicArray_t*)arr;
    for (int i = 0; i < myArr->m_Size; i++) {
        // 利用回调函数,让用户告诉我们如何对比数据
        if (myCompare(myArr->pAddr[i], data)) {
            removeByPos_dynamicArray(arr, i);
            break;
        }
    }
}

/**
 * @brief 销毁数组
 *
 * @param arr 数组指针
 */
void destroy_dynamicArray(DynamicArray arr) {
    if (arr == NULL) {
        return;
    }
    dynamicArray_t* myArr = (dynamicArray_t*)arr;
    // 内部维护在堆区的数组指针先释放
    if (myArr->pAddr != NULL) {
        free(myArr->pAddr);
        myArr->pAddr = NULL;
    }
    free(myArr);
}

队列

队列是一种线性数据结构,元素从队列的尾部插入,从队列的头部删除。队列遵循先进先出的原则,即最先插入的元素最先被删除。

队列的链式存储

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义不透明指针类型
typedef struct LinkQueue* LinkQueuePtr;
// 定义链表节点结构(内部结构,不对外暴露)
typedef struct LinkNode {
    struct LinkNode* next;  // 指向下一个节点的指针
} LinkNode_t;

// 初始化队列
LinkQueuePtr init_LinkQueue(void);

// 判断队列是否为空
int isEmpty_LinkQueue(LinkQueuePtr queue);

// 入队操作
void push_LinkQueue(LinkQueuePtr queue, void* data);

// 出队操作
void* pop_LinkQueue(LinkQueuePtr queue);

// 返回队头元素
void* front_LinkQueue(LinkQueuePtr queue);

// 返回队尾元素
void* back_LinkQueue(LinkQueuePtr queue);

// 返回队列大小
int size_LinkQueue(LinkQueuePtr queue);

// 销毁队列
void destroy_LinkQueue(LinkQueuePtr queue);
#include "LinkQueue.h"

// 定义队列结构(内部结构,不对外暴露)
typedef struct LinkQueue {
    LinkNode_t header;  // 头节点
    int m_Size;         // 队列大小
    LinkNode_t* pTail;  // 尾节点指针
} LinkQueue_t;

// 初始化队列
LinkQueuePtr init_LinkQueue(void) {
    LinkQueue_t* myQueue = (LinkQueue_t*)malloc(sizeof(LinkQueue_t));
    if (myQueue == NULL) {
        printf("内存分配失败\n");
        return NULL;
    }
    myQueue->header.next = NULL;
    myQueue->m_Size = 0;
    myQueue->pTail = &myQueue->header; // 初始时尾节点指向头节点

    return myQueue;
}

// 判断队列是否为空
int isEmpty_LinkQueue(LinkQueuePtr queue) {
    LinkQueue_t* myQueue = (LinkQueue_t*)queue;
    if (myQueue == NULL) {
        return -1; // 返回-1表示错误
    }
    return myQueue->m_Size == 0;
}

// 入队操作
void push_LinkQueue(LinkQueuePtr queue, void* data) {
    if (queue == NULL || data == NULL) {
        return;
    }

    LinkQueue_t* myQueue = (LinkQueue_t*)queue;
    LinkNode_t* newNode = (LinkNode_t*)data;

    // 新节点的next指针置为NULL
    newNode->next = NULL;

    // 如果队列为空,头节点的next指向新节点
    if (isEmpty_LinkQueue(queue)) {
        myQueue->header.next = newNode;
    }
    else {
        // 否则,尾节点的next指向新节点
        myQueue->pTail->next = newNode;
    }

    // 更新尾节点
    myQueue->pTail = newNode;
    myQueue->m_Size++;
}

// 出队操作
void* pop_LinkQueue(LinkQueuePtr queue) {
    if (queue == NULL) {
        return NULL;
    }

    LinkQueue_t* myQueue = (LinkQueue_t*)queue;

    // 如果队列为空,返回NULL
    if (isEmpty_LinkQueue(queue)) {
        return NULL;
    }

    // 获取第一个有数据的节点
    LinkNode_t* ptr = myQueue->header.next;

    // 更新头节点的next指针
    myQueue->header.next = ptr->next;

    // 如果队列中只有一个元素,更新尾节点
    if (myQueue->m_Size == 1) {
        myQueue->pTail = &myQueue->header;
    }

    myQueue->m_Size--;

    return ptr;
}

// 返回队头元素
void* front_LinkQueue(LinkQueuePtr queue) {
    if (queue == NULL) {
        return NULL;
    }

    LinkQueue_t* myQueue = (LinkQueue_t*)queue;

    // 如果队列为空,返回NULL
    if (isEmpty_LinkQueue(queue)) {
        return NULL;
    }

    return myQueue->header.next;
}

// 返回队尾元素
void* back_LinkQueue(LinkQueuePtr queue) {
    if (queue == NULL) {
        return NULL;
    }

    LinkQueue_t* myQueue = (LinkQueue_t*)queue;

    // 如果队列为空,返回NULL
    if (isEmpty_LinkQueue(queue)) {
        return NULL;
    }

    return myQueue->pTail;
}

// 返回队列大小
int size_LinkQueue(LinkQueuePtr queue) {
    if (queue == NULL) {
        return -1; // 返回-1表示错误
    }

    LinkQueue_t* myQueue = (LinkQueue_t*)queue;

    return myQueue->m_Size;
}

// 销毁队列
void destroy_LinkQueue(LinkQueuePtr queue) {
    if (queue == NULL) {
        return;
    }

    LinkQueue_t* myQueue = (LinkQueue_t*)queue;

    // 释放队列中的所有节点
    while (!isEmpty_LinkQueue(queue)) {
        LinkNode_t* ptr = pop_LinkQueue(queue);
        free(ptr);
    }

    // 释放队列本身的内存
    free(myQueue);
    queue = NULL;
}

队列的顺序存储

#pragma once

// 定义队列的别名
typedef void* SeqQueue;

// 初始化队列
SeqQueue init_SeqQueue(void);

// 入队
void enqueue_SeqQueue(SeqQueue queue, void* data);

// 出队
void dequeue_SeqQueue(SeqQueue queue);

// 返回队首元素
void* front_SeqQueue(SeqQueue queue);

// 返回队列大小
int size_SeqQueue(SeqQueue queue);

// 判断队列是否为空
int isEmpty_SeqQueue(SeqQueue queue);

// 销毁队列
void destroy_SeqQueue(SeqQueue queue);
#include "seqQueue.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define QUEUE_MAX_SIZE 1024  // 定义队列的最大容量

// 队列结构体
typedef struct SQueue {
    // 队列中数组
    void* data[QUEUE_MAX_SIZE];
    int m_Front;  // 队首指针
    int m_Rear;   // 队尾指针
    int m_Size;   // 队列大小
} SeqQueue_t;

/**
 * @brief 初始化队列
 *
 * @return SeqQueue 返回初始化后的队列指针,如果内存分配失败则返回NULL
 */
SeqQueue init_SeqQueue(void) {
    // 分配队列结构体内存
    SeqQueue_t* myQueue = malloc(sizeof(SeqQueue_t));
    if (myQueue == NULL) {
        // 内存分配失败,返回NULL
        return NULL;
    }
    // 初始化队列属性
    myQueue->m_Front = 0;
    myQueue->m_Rear = 0;
    myQueue->m_Size = 0;
    memset(myQueue->data, 0, sizeof(void*) * QUEUE_MAX_SIZE);
    return myQueue;
}

/**
 * @brief 入队
 *
 * @param queue 队列指针
 * @param data 要入队的数据指针
 */
void enqueue_SeqQueue(SeqQueue queue, void* data) {
    SeqQueue_t* myQueue = (SeqQueue_t*)queue;

    // 判断队列是否满了
    if (myQueue->m_Size == QUEUE_MAX_SIZE) {
        // 队列满,无法入队
        return;
    }
    // 数据进行尾插
    myQueue->data[myQueue->m_Rear] = data;
    myQueue->m_Rear = (myQueue->m_Rear + 1) % QUEUE_MAX_SIZE;
    myQueue->m_Size++;
}

/**
 * @brief 出队
 *
 * @param queue 队列指针
 */
void dequeue_SeqQueue(SeqQueue queue) {
    SeqQueue_t* myQueue = (SeqQueue_t*)queue;
    if (myQueue->m_Size == 0) {
        // 队列空,无法出队
        return;
    }
    // 出队操作
    myQueue->data[myQueue->m_Front] = NULL;
    myQueue->m_Front = (myQueue->m_Front + 1) % QUEUE_MAX_SIZE;
    myQueue->m_Size--;
}

/**
 * @brief 返回队首元素
 *
 * @param queue 队列指针
 * @return void* 返回队首元素的指针,如果队列为空则返回NULL
 */
void* front_SeqQueue(SeqQueue queue) {
    SeqQueue_t* myQueue = (SeqQueue_t*)queue;
    if (myQueue->m_Size == 0) {
        // 队列空,返回NULL
        return NULL;
    }
    // 返回队首元素
    return myQueue->data[myQueue->m_Front];
}

/**
 * @brief 返回队列大小
 *
 * @param queue 队列指针
 * @return int 返回队列的大小
 */
int size_SeqQueue(SeqQueue queue) {
    SeqQueue_t* myQueue = (SeqQueue_t*)queue;
    return myQueue->m_Size;
}

/**
 * @brief 判断队列是否为空
 *
 * @param queue 队列指针
 * @return int 返回1表示队列为空,返回0表示队列不为空,返回-1表示队列指针为空
 */
int isEmpty_SeqQueue(SeqQueue queue) {
    SeqQueue_t* myQueue = (SeqQueue_t*)queue;
    if (myQueue == NULL) {
        // 队列为空,返回-1
        return -1;
    }
    if (myQueue->m_Size == 0) {
        // 队列为空,返回1
        return 1;
    }
    // 队列不为空,返回0
    return 0;
}

/**
 * @brief 销毁队列
 *
 * @param queue 队列指针
 */
void destroy_SeqQueue(SeqQueue queue) {
    if (queue == NULL) {
        // 队列为空,直接返回
        return;
    }
    // 释放队列结构体内存
    free(queue);
    queue = NULL;
}

栈的顺序存储

#pragma once

// 定义栈的别名
typedef void* SeqStack;

// 初始化栈
SeqStack init_SeqStack(void);

// 入栈
void push_SeqStack(SeqStack stack, void* data);

// 出栈
void pop_SeqStack(SeqStack stack);

// 返回栈顶元素
void* top_SeqStack(SeqStack stack);

// 返回栈大小
int size_SeqStack(SeqStack stack);

// 判断栈是否为空
int isEmpty_SeqStack(SeqStack stack);

// 销毁栈
void destroy_SeqStack(SeqStack stack);

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

#define STACK_MAX_SIZE 1024  // 定义栈的最大容量

// 栈结构体
typedef struct SStack {
    // 栈中数组
    void* data[STACK_MAX_SIZE];
    int m_Size;  // 栈的大小
} SeqStack_t;

/**
 * @brief 初始化栈
 *
 * @return SeqStack 返回初始化后的栈指针,如果内存分配失败则返回NULL
 */
SeqStack init_SeqStack(void) {
    // 分配栈结构体内存
    SeqStack_t* myStack = malloc(sizeof(SeqStack_t));
    if (myStack == NULL) {
        // 内存分配失败,返回NULL
        return NULL;
    }
    // 初始化栈属性
    myStack->m_Size = 0;
    memset(myStack->data, 0, sizeof(void*) * STACK_MAX_SIZE);
    return myStack;
}

/**
 * @brief 入栈
 *
 * @param stack 栈指针
 * @param data 要入栈的数据指针
 */
void push_SeqStack(SeqStack stack, void* data) {
    SeqStack_t* myStack = (SeqStack_t*)stack;

    // 判断栈是否满了
    if (myStack->m_Size == STACK_MAX_SIZE) {
        // 栈满,无法入栈
        return;
    }
    // 数据进行尾插
    myStack->data[myStack->m_Size++] = data;
}

/**
 * @brief 出栈
 *
 * @param stack 栈指针
 */
void pop_SeqStack(SeqStack stack) {
    SeqStack_t* myStack = (SeqStack_t*)stack;
    if (myStack->m_Size == 0) {
        // 栈空,无法出栈
        return;
    }
    // 出栈操作
    myStack->data[--myStack->m_Size] = NULL;
}

/**
 * @brief 返回栈顶元素
 *
 * @param stack 栈指针
 * @return void* 返回栈顶元素的指针,如果栈为空则返回NULL
 */
void* top_SeqStack(SeqStack stack) {
    SeqStack_t* myStack = (SeqStack_t*)stack;
    if (myStack->m_Size == 0) {
        // 栈空,返回NULL
        return NULL;
    }
    // 返回栈顶元素
    return myStack->data[myStack->m_Size - 1];
}

/**
 * @brief 返回栈大小
 *
 * @param stack 栈指针
 * @return int 返回栈的大小
 */
int size_SeqStack(SeqStack stack) {
    SeqStack_t* myStack = (SeqStack_t*)stack;
    return myStack->m_Size;
}

/**
 * @brief 判断栈是否为空
 *
 * @param stack 栈指针
 * @return int 返回1表示栈为空,返回0表示栈不为空,返回-1表示栈指针为空
 */
int isEmpty_SeqStack(SeqStack stack) {
    SeqStack_t* myStack = (SeqStack_t*)stack;
    if (myStack == NULL) {
        // 栈为空,返回-1
        return -1;
    }
    if (myStack->m_Size == 0) {
        // 栈为空,返回1
        return 1;
    }
    // 栈不为空,返回0
    return 0;
}

/**
 * @brief 销毁栈
 *
 * @param stack 栈指针
 */
void destroy_SeqStack(SeqStack stack) {
    if (stack == NULL) {
        // 栈为空,直接返回
        return;
    }
    // 释放栈结构体内存
    free(stack);
    stack = NULL;
}

栈的链式存储

#pragma once
// 链表节点结构体
typedef struct linkNode {
    // 维护指针域
    struct linkNode* next;
} LinkNode_t;
// 定义栈的别名
typedef void* LinkStack;

// 初始化栈
LinkStack init_LinkStack(void);

// 入栈
void push_LinkStack(LinkStack stack, void* data);

// 出栈
void pop_LinkStack(LinkStack stack);

// 返回栈顶元素
void* top_LinkStack(LinkStack stack);

// 判断栈是否为空
int isEmpty_LinkStack(LinkStack stack);

// 销毁栈
void destroy_LinkStack(LinkStack stack);
#include "liststack.h"
#include <stdio.h>
#include <stdlib.h>


// 栈结构体
typedef struct {
    LinkNode_t pHeader;  // 头节点
    int m_Size;          // 栈的大小
} LinkStack_t;

/**
 * @brief 初始化栈
 *
 * @return LinkStack 返回初始化后的栈指针,如果内存分配失败则返回NULL
 */
LinkStack init_LinkStack(void) {
    // 分配栈结构体内存
    LinkStack_t* myStack = malloc(sizeof(LinkStack_t));
    if (myStack == NULL) {
        // 内存分配失败,返回NULL
        return NULL;
    }
    // 初始化栈属性
    myStack->pHeader.next = NULL;
    myStack->m_Size = 0;
    return myStack;
}

/**
 * @brief 入栈
 *
 * @param stack 栈指针
 * @param data 要入栈的数据指针
 */
void push_LinkStack(LinkStack stack, void* data) {
    if (stack == NULL || data == NULL) {
        // 栈或数据为空,直接返回
        return;
    }
    LinkStack_t* myStack = (LinkStack_t*)stack;
    // 取出用户的前四个字节
    LinkNode_t* newNode = (LinkNode_t*)data;
    // 建立节点之间的关系 头插入
    newNode->next = myStack->pHeader.next;
    myStack->pHeader.next = newNode;
    // 更新栈的大小
    myStack->m_Size++;
}

/**
 * @brief 出栈
 *
 * @param stack 栈指针
 */
void pop_LinkStack(LinkStack stack) {
    if (stack == NULL) {
        // 栈为空,直接返回
        return;
    }
    LinkStack_t* myStack = (LinkStack_t*)stack;
    // 本质头删
    if (myStack->m_Size == 0) {
        // 栈为空,无法出栈
        return;
    }
    // 创建指向第一个节点的指针
    LinkNode_t* pFirst = myStack->pHeader.next;
    // 更新节点指向
    myStack->pHeader.next = pFirst->next;
    // 更新栈的大小
    myStack->m_Size--;
}

/**
 * @brief 返回栈顶元素
 *
 * @param stack 栈指针
 * @return void* 返回栈顶元素的指针,如果栈为空则返回NULL
 */
void* top_LinkStack(LinkStack stack) {
    if (stack == NULL) {
        // 栈为空,返回NULL
        return NULL;
    }
    LinkStack_t* myStack = (LinkStack_t*)stack;
    // 本质头删
    if (myStack->m_Size == 0) {
        // 栈为空,返回NULL
        return NULL;
    }
    // 返回栈顶元素
    return myStack->pHeader.next;
}

/**
 * @brief 判断栈是否为空
 *
 * @param stack 栈指针
 * @return int 返回1表示栈为空,返回0表示栈不为空,返回-1表示栈指针为空
 */
int isEmpty_LinkStack(LinkStack stack) {
    if (stack == NULL) {
        // 栈为空,返回-1
        return -1;
    }
    LinkStack_t* myStack = (LinkStack_t*)stack;
    if (myStack->m_Size == 0) {
        // 栈为空,返回1
        return 1;
    }
    // 栈不为空,返回0
    return 0;
}

/**
 * @brief 销毁栈
 *
 * @param stack 栈指针
 */
void destroy_LinkStack(LinkStack stack) {
    if (stack == NULL) {
        // 栈为空,直接返回
        return;
    }
    // 释放栈结构体内存
    free(stack);
    stack = NULL;
}
   LinkStack_t* myStack = (LinkStack_t*)stack;
    // 本质头删
    if (myStack->m_Size == 0) {
        // 栈为空,无法出栈
        return;
    }
    // 创建指向第一个节点的指针
    LinkNode_t* pFirst = myStack->pHeader.next;
    // 更新节点指向
    myStack->pHeader.next = pFirst->next;
    // 更新栈的大小
    myStack->m_Size--;
}

/**
 * @brief 返回栈顶元素
 *
 * @param stack 栈指针
 * @return void* 返回栈顶元素的指针,如果栈为空则返回NULL
 */
void* top_LinkStack(LinkStack stack) {
    if (stack == NULL) {
        // 栈为空,返回NULL
        return NULL;
    }
    LinkStack_t* myStack = (LinkStack_t*)stack;
    // 本质头删
    if (myStack->m_Size == 0) {
        // 栈为空,返回NULL
        return NULL;
    }
    // 返回栈顶元素
    return myStack->pHeader.next;
}

/**
 * @brief 判断栈是否为空
 *
 * @param stack 栈指针
 * @return int 返回1表示栈为空,返回0表示栈不为空,返回-1表示栈指针为空
 */
int isEmpty_LinkStack(LinkStack stack) {
    if (stack == NULL) {
        // 栈为空,返回-1
        return -1;
    }
    LinkStack_t* myStack = (LinkStack_t*)stack;
    if (myStack->m_Size == 0) {
        // 栈为空,返回1
        return 1;
    }
    // 栈不为空,返回0
    return 0;
}

/**
 * @brief 销毁栈
 *
 * @param stack 栈指针
 */
void destroy_LinkStack(LinkStack stack) {
    if (stack == NULL) {
        // 栈为空,直接返回
        return;
    }
    // 释放栈结构体内存
    free(stack);
    stack = NULL;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值