当前位置: 首页 > article >正文

数据结构代码分享

单向链表

slist.h
#ifndef __SLIST_H
#define __SLIST_H

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

// 定义单链表结构
typedef int DATA;

typedef struct Node
{
	DATA data;		    // 存储数据---数据域
	struct Node *next;  // 存储下一个节点的地址---指针域
} NODE;

// 链表创建
int slist_create(NODE**,DATA);】.

// 向链表头部插入一个节点数据(头插法)
int slist_addHead(NODE**,DATA);

// 向链表尾部插入一个节点数据(尾插法)
int slist_addTail(NODE**,DATA);

// 向链表中间插入一个节点数据(中间插法)
int slist_insert(NODE**,DATA,DATA);

// 遍历链表数据
void slist_showAll(const NODE* head);

// 回收链表
void slist_destroy(NODE** head);

// 链表数据查询
NODE* slist_find(const NODE *head,DATA data);
// 更新链表数据
int slist_update(const NODE *head,DATA old_data,DATA new_data);

// 删除链表数据(剔除节点,不是真正意义上的删除)
int slist_delete(NODE**,DATA);

#endif



slist.c
#include "slist.h"

/*
@function:   int slist_create(NODE** head,DATA data);
@berif:      创建单项链表
@argument:   head: 指向头指针变量的地址,用来接收首节点地址
             data: 存储在节点中的数据
@return :    成功返回 0
             失败返回 -1
*/
int slist_create(NODE **head, DATA data)
{
    // 申请内存
    NODE *p = (NODE *)malloc(sizeof(NODE));
    // 校验
    if (!p)
    {
        return -1;
    }
    // 赋值操作
    p->data = data;
    p->next = NULL;

    *head = p;

    return 0;
}

/*
@function:   int slist_addHead(NODE** head,DATA data);
@berif:      向链表头部插入一个节点数据(头插法)
@argument:   head: 指向头指针变量的地址,用来接收首节点地址
             data: 存储在新节点中的数据
@return :    成功返回 0
             失败返回 -1
*/
int slist_addHead(NODE **head, DATA data)
{
    // 创建一个新节点(申请内存)
    NODE *p = (NODE *)malloc(sizeof(NODE));
    // 校验
    if (!p)
    {
        return -1;
    }
    // 给节点添加新数据(创建节点的目的是存储数据)
    p->data = data;
    // 新节点指向原本的head节点
    p->next = *head;

    // 我们要让p作为我们新的head
    *head = p;

    return 0;
}

/*
@function:   int slist_addTail(NODE** head,DATA data);
@berif:      向链表尾部插入一个节点数据(尾插法)
@argument:   head: 指向头指针变量的地址,用来接收首节点地址
             data: 存储在新节点中的数据
@return :    成功返回 0
             失败返回 -1
*/
int slist_addTail(NODE **head, DATA data)
{
    // 创建一个新节点(申请内存)
    NODE *pNew = (NODE *)malloc(sizeof(NODE));
    // 校验
    if (!pNew)
    {
        return -1;
    }
 // 赋值操作
    pNew->data = data; // 存数据
    pNew->next = NULL; // 因为是最后一个节点,所有没有指向

    // 获取尾部节点,默认head头结点就是尾结点,p用来保存真实的尾结点
    NODE *p = *head, *q = NULL;
    if (!p)
    {
        // 如果说头节点不存在,我们直接将新节点作为头结点,一般不会发生
        *head = pNew;
        return 0;
    }

    // 通过一个循环,找尾结点
    while (p)
    {
        // 为什么要定义q,因为p是在变化的
        q = p;
        p = p->next;// 指针向下指
    }

    // 让原本的尾结点指向新插入的的节点,此时新插入的节点变成了尾结点
    q->next = pNew;
    

    return 0;
}


/*
@function:   int slist_insert(NODE** head,DATA pos ,DATA data);
@berif:      向链表节点值为pos的位置插入一个节点数据data
@argument:   head: 指向头指针变量的地址
             pos:  插入节点位置的节点数据
             data: 存储在新节点中的数据
@return :    成功返回 0
             失败返回 -1
*/
int slist_insert(NODE** head,DATA pos,DATA data)
{
    // 创建一个新节点,并申请内存
    NODE *pNew = (NODE*)malloc(sizeof(NODE));
    if(!pNew)
    {
perror("内存申请失败!");
        return -1;
    }
    // 给新节点赋初值
    pNew->data = data;
    pNew->next = NULL;

    // 声明变量,p是pos对应位置的节点,默认是头结点,q是pos对应节点的上一个节点
    NODE *p = *head,*q = NULL;

    // 第一种情况:头结点不存在
    if(!p)
    {
        // 新节点pNew作为头结点
        *head = pNew;
        return 0;
    }
    // 第二种情况:只有头结点
    if(memcmp(&(p->data),&pos,sizeof(DATA)) == 0)
    {
        // 头插法
        // 新节点的next指向head节点
        pNew->next = *head;
        // 改变指向,将pNew作为新的头结点
        *head = pNew;
        return 0;
    }
    // 第三种情况:既有头结点,也有普通节点
    while (p)
    {
        // 找pos对应位置的节点
        if(memcmp(&(p->data),&pos,sizeof(DATA)) == 0)
        {
            // pNew在p前
            pNew->next = p;
            // pNew在q后
            q->next = pNew;
            return 0;
        }
        q = p;// q在p的前一位,一前(q)一后(p)
        p = p ->next;
    }
    // 尾插法
 q->next = pNew;
    
    return 0;
}

/*
@function:   NODE* slist_find(const NODE* head,DATA data);
@berif:      查找链表数据data
@argument:   head: 指向头指针变量
             data: 待查找的数据
@return :    成功返回节点的地址
             失败返回NULL
*/
NODE* slist_find(const NODE *head,DATA data)
{
    // 创建一个变量,用来接收链表
    const NODE* p = head;

    while(p)
    {
        if(memcmp(&(p->data),&data,sizeof(DATA))==0)
        {
            return (NODE*)p;
        }
        // 移动节点
        p = p->next;
    }
    return NULL;
}

/*
@function:   int slist_update(const NODE* head,DATA old_data,DATA new_data);
@berif:      更新链表数据old_data 为 new_data
@argument:   head: 指向头指针变量
             old_data:  待更新的节点数据
             new_data: 更新后的节点数据
@return :    成功返回  0
             失败返回  -1
*/
int slist_update(const NODE* head,DATA old_data,DATA new_data)
{
    NODE* p = NULL;
    if(!(p = slist_find(head,old_data)))
    {
 return -1;
    }
    p->data = new_data;

    return 0;

}

/*
@function:   void slist_showAll(const NODE* head);
@berif:      遍历链表数据
@argument:   head: 指向头指针变量
@return :    无
*/
void slist_showAll(const NODE* head)
{
    // 创建一个变量用来接收链表
    const NODE* p = head;

    // 遍历链表
    while (p)
    {
        printf("%d ",p->data);
        p = p->next;
    }
    printf("\n");
    
}

/*
@function:   int slist_delete(NODE** head,DATA data);
@berif:      删除链表中节点值为data的节点
@argument:   head: 指向头指针变量的地址
             data: 删除节点中的数据
@return :    成功返回 0
             失败返回 -1
*/
int slist_delete(NODE** head,DATA data)
{
    // 指针尾随
    NODE *p = *head,*q = NULL;
    
    // 第一种情况:头结点不存在(链表本身不存在),无法操作
    if(!p)
 {
       return -1; 
    }
    // 第二种情况:只有一个节点
    if(memcmp(&(p->data),&data,sizeof(DATA)) == 0)
    {
        *head = p -> next;
        free(p);
        return 0;
    }
    // 第三种情况:有多个节点
    while (p)
    {
        if(memcmp(&(p->data),&data,sizeof(DATA)) == 0)
        {
            q->next = p->next;// p的上一个节点的next指向p的下一个节点
            // 这个回收不会影响到链表的删除
            free(p);
            return 0;
        }

        q = p;
        p = p->next;// p->next代表的是p的下一个节点,将p的下一个节点赋值给p,相当于p移动了一位
    }

    return -1;
    

}

/*
@function:   void slist_destroy(NODE** head);
@berif:      回收链表
@argument:   head: 指向头指针变量的地址
@return :    无
*/
void slist_destroy(NODE** head)
{
    // 指针尾随
    NODE *p = *head,*q = NULL;

    while(p)
    {
q = p;// 12
        p = p->next;// 13
        // 回收前一个节点
        free(q);
    }
    *head = NULL;

}



Slist_main.c
#include "slist.h"
#define DELETE 1
int main()
{
    NODE *head = NULL;

    if (slist_create(&head, 888) < 0)
    {
        perror("单链表创建失败!");
        // exit(0);
        return -1;
    }
    printf("单链表创建成功!\n");

    slist_addTail(&head, 999);
    slist_addTail(&head, 222);
    slist_addTail(&head, 666);
    slist_addTail(&head, 777);
    // 运行效果:999 222 666 777

    slist_addHead(&head, 555);
    // 运行效果:555 999 222 666 777

    slist_insert(&head, 555, 1024);
    // 运行效果:1024 555 999 222 666 777
    slist_insert(&head, 222, 1080);
    // 运行效果:1024 555 999 1080 222 666 777
    slist_showAll(head);

    DATA data;
 while (1)
    {
#ifdef DELETE
        printf("请输入要删除的数据:");
        scanf("%d", &data);
        if (data == -1)
            break;
        if (slist_delete(&head, data) < 0)
        {
            puts("删除失败,请重试");
            continue;
        }
        slist_showAll(head);
#else
        NODE *pFind = NULL;
        DATA newdata = 512;

        printf("请输入要查找的数据:");
        scanf("%d", &data);
        if (data == -1)
            break;
        // if(!(pFind = slist_find(head,data)))
        if (slist_update(head, data, newdata) == -1)
        {
            puts("查找的数据不存在,请重试");
            continue;
        }
        // printf("查找数据:%d  内存地址:%p\n",pFind -> data, &(pFind -> data));
        slist_showAll(head);
#endif
    }

    slist_destroy(&head);
    puts("====销毁后====");
    slist_showAll(head);

    return 0;
}

双向链表

dlist.h
#ifndef __DLIST_H
#define __DLIST_H

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

// 定义链表节点中数据的类型,本次案例使用int类型
typedef int DATA;

// 定义节点
typedef struct node
{
    DATA          data; // 数据
    struct  node *prev; // 前驱指针
    struct  node *next; // 后继指针
}NODE;

// 创建链表(初始化)
int dlist_create(NODE**,DATA);

// 向链表头部插入数据(头插法)
int dlist_addHead(NODE**,DATA);

// 向链表尾部插入数据(尾插法)
int dlist_addTail(NODE**,DATA);

// 向链表任意位置插入数据(中间插法)
int dlist_insert(NODE**,DATA,DATA);

// 链表数据遍历
void dlist_showAll(const NODE*);

// 链表数据查询
NODE* dlist_find(const NODE*,DATA);
// 链表数据更新
int dlist_update(const NODE*,DATA,DATA);

// 链表数据删除
int dlist_delete(NODE**,DATA);

// 链表回收
void dlist_destroy(NODE**);
#endif


dlist.c
#include "dlist.h"

/**
 * @function:   int dlist_create(NODE**,DATA);
 * @berif:      创建双向链表
 * @argument:   head: 指向头指针变量的地址,用来接收首节点地址
 *              data: 存储在节点中的数据
 * @return :    成功返回 0
 *              失败返回 -1
 */
int dlist_create(NODE **head, DATA data)
{
    // 创建一个节点(申请内存)
    NODE *pNew = (NODE *)malloc(sizeof(NODE));
    if (!pNew)
    {
        perror("内存申请失败!");
        return -1;
    }

    // 节点的初始化
    pNew->data = data;
    pNew->prev = pNew->next = NULL; // 给前驱指针和后继指针都赋值为NULL

    // 将pNew作为头结点
    *head = pNew;
    return 0;
}

/**
 * @function:   int dlist_addHead(NODE**,DATA);
 * @berif:      向链表头部插入数据
 * @argument:   head: 指向头指针变量的地址,用来接收首节点地址
 *              data: 存储在节点中的数据
 * @return :    成功返回 0
 *              失败返回 -1
 */
int dlist_addHead(NODE **head, DATA data)
{
    // 创建一个节点,申请内存
    NODE *pNew = (NODE *)malloc(sizeof(NODE));
    // 校验
    if (!pNew)
    {
        perror("内存申请失败!");
        return -1;
    }
    // 给节点赋值
    pNew->data = data;
    pNew->prev = NULL;
    pNew->next = *head;

    // 如果头结点存在,需要设置head.prev指向pNew
    if (*head)
    {
        (*head)->prev = pNew;
    }
    // 将pNew作为新的头结点
    *head = pNew;

    return 0;
}

/**
 * @function:   int dlist_addTail(NODE**,DATA);
 * @berif:      向链表尾部插入数据
 * @argument:   head: 指向头指针变量的地址,用来接收首节点地址
 *              data: 存储在节点中的数据
 * @return :    成功返回 0
 *              失败返回 -1
 */
int dlist_addTail(NODE **head, DATA data)
{
    // 创建一个节点,申请内存
NODE *pNew = (NODE *)malloc(sizeof(NODE));
    if (!pNew)
    {
        perror("内存申请失败!");
        return -1;
    }

    // 给节点赋初值
    pNew->data = data;
    pNew->prev = pNew->next = NULL;

    // 定义一个变量,用来存储尾结点
    NODE *p = *head;

    // 第一种情况:没有节点,pNew作为头结点
    if (!p)
    {
        *head = pNew;
        return 0;
    }

    // 第二种情况:有节点,向末尾添加pNew
    while (p->next)
    {
        // 移动p的位置
        p = p->next;
    }

    // 末尾的p节点跟pNew建立联系,此时pNew称为尾结点
    p->next = pNew;
    pNew->prev = p;

    return 0;
}

/**
 * @function:   int dlist_insert(NODE**,DATA,DATA);
 * @berif:      向链表任意位置插入数据(中间插法)
 * @argument:   head: 指向头指针变量的地址,用来接收首节点地址
 *              pos:目标位置数据
 *              data: 存储在节点中的数据
 * @return :    成功返回 0
 *              失败返回 -1
 */
int dlist_insert(NODE **head, DATA pos, DATA data)
{
    // 创建节点,申请内存
    NODE *pNew = (NODE *)malloc(sizeof(NODE));
    if (!pNew)
    {
        perror("内存申请失败!");
        return -1;
    }

    // 给节点赋初值
    pNew->data = data;
    pNew->prev = pNew->next = NULL;

    NODE *p = *head, *q = NULL;

    // 第一种情况:没有节点,pNew作为头结点
    if (!p)
    {
        *head = pNew;
        return 0;
    }

    // 第二种情况:pos对应的节点刚好是头结点(有效节点是头结点,只有一个节点的时候)
    if (memcmp(&(p->data), &pos, sizeof(DATA)) == 0)
    {
        pNew->next = p;
        p->prev = pNew;
        *head = pNew;
        return 0;
    }
    // 第三种情况:pos对应的节点不是头结点(有效节点超过两个)
    while (p) // p 判断当前节点是否为NULL,p->next 判断写一个节点是否为NULL
    {
        if (memcmp(&(p->data), &pos, sizeof(DATA)) == 0)
        {
            pNew->next = p;
            pNew->prev = q;
            p->prev = pNew;
            q->next = pNew;
            return 0;
        }
        // 记录当前位置(上一个节点的位置)
 q = p;
        // 记录下一个节点的位置,也就是更新后的p
        p = p->next;
    }
    // 如果在链表中找不到pos对应的节点,就尾插
    q->next = pNew;
    pNew->prev = q;

    return 0;
}

/**
 * @function:   void dlist_showAll(const NODE*);
 * @berif:      向链表任意位置插入数据(中间插法)
 * @argument:   head: 指向头指针变量的地址,用来接收首节点地址
 *              pos:目标位置数据
 *              data: 存储在节点中的数据
 * @return :    成功返回 0
 *              失败返回 -1
 */
void dlist_showAll(const NODE *head)
{
    const NODE *p = head;
    while (p)
    {
        printf("%d ", p->data);
        // 向后遍历
        p = p->next;
        // 向前遍历
        // p = p->prev;
    }
    printf("\n");
}

/**
 * @function:   NODE* dlist_find(const NODE*,DATA);
 * @berif:      链表数据查询(根据指定的数据查找节点)
 * @argument:   head: 指向头指针变量的地址,用来接收首节点地址
 *              data: 要检索的数据
 * @return :    成功返回 NODE*
 *              失败返回 NULL
 */
NODE *dlist_find(const NODE *head, DATA data)
{
 // 创建一个变量去接收链表
    const NODE *p = head;

    while (p)
    {
        if (memcmp(&(p->data), &data, sizeof(DATA)) == 0)
        {
            return (NODE *)p;
        }

        p = p->next;
    }
    return NULL;
}

//
/**
 * @function:   dlist_update(const NODE*,DATA,DATA);
 * @berif:      链表数据更新
 * @argument:   head: 指向头指针变量的地址,用来接收首节点地址
 *              old_data:源数据
 *              new_data: 目标数据
 * @return :    成功返回 0
 *              失败返回 -1
 */
int dlist_update(const NODE *head, DATA old_data, DATA new_data)
{
    // 用来接收查询到的节点
    NODE *pFind = NULL;

    // 利用刚刚写的查询函数,查询
    if (!(pFind = dlist_find(head, old_data)))
    {
        return -1;
    }
    // 更新数据
    pFind->data = new_data;

    return 0;
}

/**
 * @function:   dlist_delete(NODE**,DATA);
 * @berif:      链表数据删除
 * @argument:   head: 指向头指针变量的地址,用来接收首节点地址
 *              data: 需要删除的数据
 * @return :    成功返回 0
 *              失败返回 -1
 */
int dlist_delete(NODE **head, DATA data)
{
    // 记录需要删除的节点的位置
    NODE *p = *head;

    // 第一种情况:链表不存在
    if (!p)
    {
        return -1;
    }
    // 第二种情况:删除的数据对应的节点正好是头结点
    if (memcmp(&(p->data), &data, sizeof(DATA)) == 0)
    {
        // 1. 链表中只有一个节点
        if (p->next == NULL)
        {
            free(p);
            *head = NULL;
            return 0;
        }
        // 2. 链表中有两个以上节点
        // 执行下列代码之前,head和p都指向头结点,下面代码的意思是:将p节点的下一个节点作为新的头结点
        *head = p->next;
        // 解除p的引用关系(下一个节点指向它的关系)
        p->next->prev = NULL;
        // 回收p
        free(p);

        return 0;
    }

    // 正常删除:链表中要删除的节点不是头结点
    while (p)
    {
        if (memcmp(&(p->data), &data, sizeof(DATA)) == 0)
        {
            // p的上一个节点的next指向p的下一个节点
            p->prev->next = p->next;
 // p是尾结点
            if(p->next==NULL)
            {
                // 解除p的上一个节点跟p的引用
                p->prev->next = NULL;
            }
            else // p不是尾结点
            {
                // p的下一个节点的prev指向p的上一个节点
                p->next->prev = p->prev;
            }
            // 回收解除引用的节点
            free(p);
            return 0;
        }

        // 改变循环条件
        p = p->next;
    }

    return -1;
}

/**
 * @function:   void dlist_destroy(NODE**);
 * @berif:      链表回收
 * @argument:   head: 指向头指针变量的地址,用来接收首节点地址
 *              old_data:源数据
 *              new_data: 目标数据
 * @return :    成功返回 0
 *              失败返回 -1
 */
void dlist_destroy(NODE **head)
{
    // p记录移动的节点,q记录需要回收的节点
    NODE *p = *head, *q = NULL;

    while (p)
    {
        // 实现指针尾随
        q = p;       // 前一个节点
        p = p->next; // 后一个节点
        // 回收q
   free(q);
    }
    *head = NULL;
}



Dlist_main.c
#include "dlist.h"

#define OP 3

int main()
{
    NODE *head = NULL;

    // if (dlist_create(&head, 666) != -1)
    // {
    //     printf("链表创建成功!\n");
    // }
    // else
    // {
    //     printf("链表创建失败!\n");
    // }

    int a[] = {1, 3, 5, 7, 9};
    int n = sizeof a / sizeof a[0];
    register int i = 0;

    for (; i < n; i++)
    {
        dlist_addTail(&head, a[i]);
    }
    dlist_addHead(&head, 888);
    dlist_insert(&head, 5, 999);

    dlist_showAll(head); // 888 1 3 999 5 7 9

    while (1)
    {
       
#if (OP == 0)   
 DATA data;
        NODE *pFind = NULL;
        printf("请输入要查找的数据(-1 退出):");
        scanf("%d", &data);
        if (data == -1)
            break;
        if (!(pFind = dlist_find(head, data)))
        {
            puts("查找的数据不存在,请重试...");
            continue;
        }
        printf("在内存地址为 %p 的内存空间中找到了 %d\n", &(pFind->data), pFind->data);
#elif (OP == 1)
        DATA data;
        NODE *pFind = NULL;
        printf("请输入要插入位置的数据(-1 退出):");
        scanf("%d", &data);
        if (data == -1)
            break;
        if (dlist_insert(&head, data, 407))
        {
            puts("插入失败,请重试...");
            continue;
        }
        dlist_showAll(head);
#elif (OP == 2)
        DATA data;
        NODE *pFind = NULL;
        printf("请输入要修改位置的数据(-1 退出):");
        scanf("%d", &data);
        if (data == -1)
            break;
        if (dlist_update(head, data, 407))
        {
            puts("修改失败,请重试...");
            continue;
        }
        dlist_showAll(head);
#else
        DATA data;
        NODE *pFind = NULL;
        printf("请输入要删除位置的数据(-1 退出):");
        scanf("%d", &data);
 if (data == -1)
            break;
        if (dlist_delete(&head, data))
        {
            puts("删除失败,请重试...");
            continue;
        }
        dlist_showAll(head);

#endif
    }

    dlist_destroy(&head);
    puts("=====回收后====");
    dlist_showAll(head);

    return 0;
}

顺序队列

squeue.h
#ifndef __SQUEUE_H
#define __SQUEUE_H

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

// 定义测试的数据类型
typedef int DATA;

// 创建顺序队列
typedef struct
{
    DATA *pData; // 队列入口,也就是我们创建的堆数组,我们入队的所有数据存储在这里
    int size;    // 队列的总容量(堆数组的大小)
    int head;    // 队头元素下标
    int tail;    // 队尾元素下标
} SQueue;

// 初始化队列
int SQ_init(SQueue *q, int num);

// 判断队列是否已满
int SQ_isfull(SQueue *q);

// 判断队尾是否为空
int SQ_isempty(SQueue *q);

// 入队
int SQ_push(SQueue *s, DATA data);

// 出队
int SQ_pop(SQueue *st, DATA *data);

// 回收队列
int SQ_free(SQueue *st);
#endif


squeue.c
#include "squeue.h"

// 初始化队列
int SQ_init(SQueue *q, int num)
{
    // 首先,给pData,也就是堆数组申请空间
    q->pData = (DATA *)calloc(sizeof(DATA), num);

    // 校验
    if (q->pData == NULL)
    {
        perror("内存申请失败!");
        return -1;
    }

    // 初始化
    q->size = num;
    // 默认头尾下标都是0,此时队列为空(当头和尾的下标相等时,队列是空的)
    q->head = q->tail = 0;

    return 0;
}

// 判断队列是否已满
int SQ_isfull(SQueue *q)
{
    return (q->tail + 1) % q->size == q->head;
}

// 判断队尾是否为空
int SQ_isempty(SQueue *q)
{
    return q->tail == q->head;
}

// 入队
int SQ_push(SQueue *s, DATA data)
{
  // 判断队列是否已满
    if (SQ_isfull(s))
    {
        return -1;
    }
    // 将数据存放到队尾
    s->pData[s->tail] = data;
    s->tail = (s->tail + 1) % s->size;

    return 0;
}

// 出队
int SQ_pop(SQueue *st, DATA *data)
{
    // 判断队列是否为空
    if (SQ_isempty(st))
        return -1;

    *data = st->pData[st->head];
    st->head = (st->head + 1) % st->size;

    return 0;
}

// 回收队列
int SQ_free(SQueue *st)
{
    if (st->pData)
    {
        free(st->pData);
        st->pData = NULL;
    }
    st->head = st->tail = 0;
}




Squeue_main.c
#include "squeue.h"
#include <stdio.h>
int main(void)
{
    SQueue    queue;

    SQ_init(&queue,10);
    register  int i = 1;    

    for(; i <= 10 ; i++) 
       SQ_push(&queue, i);

    if( -1 == SQ_push(&queue,1024))
      fprintf(stderr,"满队,入队失败!\n");

    while(!SQ_isempty(&queue))
    {
        DATA   data;
        SQ_pop(&queue,&data);
        printf("%4d",data);
    }
    printf("\n");

    SQ_free(&queue);
    return 0; 
}

sstack.h
#ifndef __SSTACK_H
#define __SSTACK_H

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

// 定义数据的类型,可以是复杂的结构体,本案例就使用int
// typedef struct Book
// {
//     int id;
//     char *name;
//     int bookId;
//     char *author;
// }DATA;

typedef int DATA;

// 顺序栈结构体
typedef struct
{
    DATA *pData;// 栈中元素的地址[12,13,14]
    int    size;// 顺序栈的大小(数组的大小)
    int    top; // 栈顶元素下标
}SeqStack;

// 初始化栈
int SStack_init(SeqStack *s,int size);

// 判断栈是否已满
int SStack_isfull(SeqStack *s);

// 判断栈是否为空
int SStack_isempty(SeqStack *s);

// 入栈|压栈
int SStack_push(SeqStack *s,DATA data);
// 出栈|弹栈(弹出指定元素)
int SStack_pop(SeqStack *s,DATA *data);

// 出栈|弹栈(弹出所有元素)

// 回收栈
int SStack_destroy(SeqStack *s);



#endif




sstack.c
#include "sstack.h"

// 初始化栈
int SStack_init(SeqStack *s,int size)
{
    // 给栈中的元素申请存储空间
    s->pData = (DATA*)calloc(sizeof(DATA),size);
    // 校验
    if(s->pData == NULL)
    {
        perror("内存申请失败!");
        return -1;
    }
    // 初始化
    s->size = size;
    s->top = -1;

    return 0;
} 

// 判断栈是否已满
int SStack_isfull(SeqStack *s)
{
    return s->top + 1 == s->size;
}
// 判断栈是否为空
int SStack_isempty(SeqStack *s)
{
    return s->top == -1;
}

// 入栈|压栈
int SStack_push(SeqStack *s,DATA data){
    // 判断栈是否已满
    if(SStack_isfull(s))
    {
        printf("顺序栈已填满!\n");
        return -1;
    }
    // 操作栈
    s->top++;// top向后偏移一位,top自增
    s->pData[s->top] = data;// 在更新后的top位置插入数据
    return 0;
}

// 出栈|弹栈(弹出指定元素)
int SStack_pop(SeqStack *s,DATA *data)
{
    // 判断栈是否为空
    if(SStack_isempty(s))
    {
        printf("顺序栈已为空!\n");
        return -1;
    }
    // 将弹出的元素返回
    *data = s->pData[s->top];
    // 改变top
    s->top--;
     
    // printf("弹出数据:%d\n",*data);

    return 0;
}


// 回收栈
int SStack_destroy(SeqStack *s){
    if(s->pData)
 {
        // 释放内存
        free(s->pData);
        s->pData = NULL;
    }
    // 重置top
    s->top = -1;
}




Sstack_main.c
#include "sstack.h"

int main()
{
    // 声明顺序栈
    SeqStack st;
    // 声明一个变量,用来接收弹出的数据
    DATA data;

    // 初始化顺序栈
    SStack_init(&st,10);

    for(int i = 0;i<15;i++)
    {
        // 入栈
        SStack_push(&st,i);
    }

    // 弹栈
    while(!SStack_isempty(&st))
    {
        SStack_pop(&st,&data);
        printf("%-4d",data);
    }
    printf("\n");


    printf("====回收栈====\n");
    SStack_destroy(&st);
  return 0;
}


http://www.kler.cn/news/283554.html

相关文章:

  • 机器视觉--光源打光技巧
  • C++中的异常处理与资源管理
  • 79、ansible-----playbook2
  • 以太坊 MEV 提案续篇:一文了解 Execution Tickets 和 Execution Auction
  • 金融涉案账户压降行动的实施成效与挑战
  • <WPF> xaml代码如何使用c#编写
  • 深入理解 Java 中 Map 和 Set 接口的高级用法
  • 【Rust光年纪】Rust多媒体处理库全面比较:探索安全高效的多媒体处理利器
  • Docker私有镜像仓库Harbor安装并推拉镜像
  • uniapp APP版本更新
  • easyExcel 填充写时,动态合并单元格
  • SQL视图:简化复杂查询的利器
  • Django+Vue社区养老管理系统的设计与实现
  • 光庭信息半年报:营收利润「双」下降,汽车软件业务竞争加剧
  • 揭晓9款敏捷团队必备的协作工具选择
  • MAC上Homebrew常用命令
  • LeetCode49题的反思
  • 基于事件总线EventBus实现邮件推送功能
  • 一些零碎的关于合约测试,ERC20调用的知识
  • 复杂工件的高效测量方案:自动化三坐标测量与影像测量技术集成
  • 工作中常用的100个知识点
  • DDR test Tool for imx9
  • [Android常见View的用法] RecyleView基本用法
  • 群晖7.2.1 半洗白后安装AME
  • Python(R)均方根误差平均绝对误差导图
  • helm学习第三篇--结合 springboot 单做
  • 深度强化学习算法(六)(附带MATLAB程序)
  • 正弦波振荡器工作原理及频率稳定性条件
  • 【JVM】OOM与调优(二)
  • C++ 设计模式——代理模式