数据结构入门3

继续, 这次是链表的应用之一. 栈

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

/*
栈, 静态内存, 操作系统分配
堆, 动态内存, 程序员手动进行分配
*/

typedef struct Node
{
    int data;
    struct Node* pNext;
}NODE, *PNODE;


typedef struct Stack
{
    PNODE pTop;
    PNODE pBottom;
}STACK, *PSTACK;


// 声明函数
void initStack(PSTACK); // 初始化栈
void push(PSTACK, int); // 入栈
void traverse(PSTACK); // 遍历栈
bool pop(PSTACK, int*); // 元素出栈


int main(void)
{
    STACK S; // STACK 等价于 struct Stack
    int val; // 保存出栈的值

    initStack(&S);
    push(&S, 1);
    push(&S, 2);
    push(&S, 3);
    push(&S, 4);
    push(&S, 5);
    push(&S, 6);
    push(&S, 7);
    push(&S, 8);
    push(&S, 9);
    traverse(&S);

    clear(&S);
    traverse(&S);

    /*
    if (pop(&S, &val))
    {
        printf("栈顶元素%i出栈成功!\n", val);
    }
    else
    {
        printf("出栈失败!\n");
    }

    traverse(&S);
    */

    return 0;
}

// 栈初始化, top和bottom指针都指向栈底
void initStack(PSTACK pS)
{
    pS->pTop = (PNODE)malloc(sizeof(NODE));

    if(NULL == pS->pTop)
    {
        printf("动态内存分配失败!\n");
        exit(-1);
    }
    else
    {
        // 此时top和bottom指针都指向pS的栈底, 直接赋值
        // 但top或bottom指向的头结点的pNext指针应该为空
        // 因为栈中一个元素也没有
        pS->pBottom = pS->pTop;
        pS->pTop->pNext = NULL; //pS->pBottom->pNext = NULL
    }
}

void push(PSTACK pS, int val)
{
    PNODE pNew = (PNODE)malloc(sizeof(NODE));
    pNew->data = val; // 将val给新入栈元素赋值

    // 只压入一个元素 pTop和pBottm 指向相同
    // 当压入元素增多, pBottom指针不会移动, pTop会随着入栈的元素向上移动
    // pNew->pNext要指向pTop的地址
    // 此时pTop指针还没移动, pTop指向原来栈顶的元素

    // 4    pNew
    // 3 <- pTop
    // 2
    // 1 <- pBottom

    pNew->pNext = pS->pTop;

    pS->pTop = pNew; // 更新栈顶指针
}

//遍历栈
traverse(PSTACK pS)
{
    PNODE p = pS->pTop;

    // 只要p不等于pBottom指针
    // 还没有遍历到底, 就一直循环遍历输出
    while (p != pS->pBottom)
    {
        printf("%i ", p->data);
        p = p->pNext;
    }
    printf("\n");

    return;
}

bool is_empty(PSTACK pS)
{
    if (pS->pTop == pS->pBottom)
        return true;
    else
        return false;
}


// pS栈的栈顶元素出栈并把出栈元素保存并返回打印
bool pop(PSTACK pS, int* pVal)
{
    //pS 为PSTACK 类型 本身存放 pS 的地址
    if(is_empty(pS))
    {
        return false;
    }
    else
    {
        PNODE r = pS->pTop;
        *pVal = r->data;
        pS->pTop = r->pNext;
        free(r);
        r = NULL;

        return true;
    }
}

// 清空栈元素
// 使用双指针, 避免单指针整个链表中断
//
void clear(PSTACK pS)
{
    // 判断是否为空 再进行下一步动作
    if(is_empty(pS))
    {
        return;
    }
    else
    {
        PNODE p = pS->pTop; // 指针指向栈顶
        PNODE q = NULL; // 暂时为空避免

        // 从栈顶遍历到栈底
        while(p != pS->pBottom)
        {
            q = p->pNext; // 保存下一结点的指针
            free(p); // 释放p的内存
            p = q; // 将q地址赋给p, 重复操作

        }

        // 清空栈元素后, 重置栈顶指针
        pS->pTop = pS->pBottom;
    }
}
posted @ 2025-06-09 12:13  鲲特牌  阅读(10)  评论(0)    收藏  举报