现在的位置: 首页 > 综合 > 正文

12-数据结构_栈

2013年10月29日 ⁄ 综合 ⁄ 共 3665字 ⁄ 字号 评论关闭

线性结构的常见应用之一   栈

一, 定义

    一种可以实现"先进后出"的存储结构(存储方式)
    只能在一端入和出

二, 分类

    如图 06-静态栈-动态栈.jpg
    1, 静态栈
        底层 以 静态数组 实现
    2, 动态栈
        底层 以 链表 实现





三, 算法

1, 节点 Node, 栈 Stack

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

// 栈
typedef struct Stack
{
    PNODE pTop;     // 栈顶
    PNODE pBottom;  // 栈底
} STACK, * PSTACK;

2, 初始化 栈, 即造出空栈    

void initStack(PSTACK pStack)
{   
    // "头结点"
    pStack->pBottom = (PNODE) malloc( sizeof(NODE) ); 
    checkMemoryAllocat(pStack->pBottom);

    pStack->pBottom->pNext = NULL;  // "头结点"指针域与空

    // 栈底指针 和 栈顶指针 都指向 "头结点"
    pStack->pTop = pStack->pBottom;
    return;
}

3, 压栈

// 压栈
void push(PSTACK pStack, int value)
{
    // 新结点
    PNODE pNew = (PNODE) malloc( sizeof(NODE) );
    checkMemoryAllocat(pNew);
    pNew->data = value;

    pNew->pNext = pStack->pTop; // 新结点的指针域 指向 栈顶
    pStack->pTop = pNew; // 栈顶 上移, 指向 新结点

    return;
}

4, 弹栈, 出栈失败(空栈), pValue保存出栈的数据

// 弹栈
bool pop(PSTACK pStack, int * pValue)
{   
    if ( isEmpty(pStack) )
    {
        return false;
    }    
    
    PNODE pTemp = pStack->pTop;     // 指向要删除的结点


    *pValue = pTemp->data;          // 记录删除结点的数据域
    
    pStack->pTop = pTemp->pNext;    // 栈顶指针 下移
    
    free(pTemp);    // 释放删除的结点
    pTemp = NULL;


    return true;
}

5, 遍历

// 遍历
void traverse(PSTACK pStack)
{
    printf("遍历-由顶到底:\n");
    PNODE p = pStack->pTop;

    for (; p != pStack->pBottom; p = p->pNext)
    {
        printf("%3d\n", p->data);
    }

    return;
}

6, 检查动态内存是否分配失败, 是则终止

void checkMemoryAllocat(PNODE pNode)
{
    if (NULL == pNode)
    {
        printf("动态内存分配失败,结束程序!");
        exit(-1);
    }
}

7, 栈是否为空

// 栈是否为空
bool isEmpty(PSTACK pStack)
{   
    if (pStack->pTop == pStack->pBottom)
    {
        return true;
    }
    return false;
}

8, 清空, 删除所有有效数据

// 清空, 删除所有有效数据, 先下移栈顶, 后释放
void clear(PSTACK pStack)
{
    PNODE pTemp = pStack->pTop; // 用于指向要释放的 结点

    // 释放所有 有效结点
    while (pStack->pTop != pStack->pBottom)
    {
        pTemp = pStack->pTop;
        pStack->pTop = pTemp->pNext;    // 栈顶下移
        // 释放 刚才出栈的结点的内存
        free(pTemp);
        pTemp = NULL;
    }

   return;
}


9, 完整代码

#include <stdio.h>
#include <malloc.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 pStack);
// 压栈
void push(PSTACK pStack, int value);
// 弹栈, 出栈失败(空栈), pValue保存出栈的数据
bool pop(PSTACK pStack, int * pValue);
// 遍历
void traverse(PSTACK pStack);
// 检查动态内存是否分配失败, 是则终止
void checkMemoryAllocat(PNODE pNode);
// 栈是否为空
bool isEmpty(PSTACK pStack);
// 清空, 删除所有有效数据
void clear(PSTACK pStack);

int main(void)
{
    STACK stack;

    // 初始化 栈
    initStack( &stack );

    // 压栈
    push(&stack, 1);
    push(&stack, 2);
    push(&stack, 3);
    push(&stack, 4);

    // 遍历
    traverse(&stack);

    // 弹栈
    int value;
    int i, count;
    printf("请输入要出栈的元素个数 : ");
    scanf("%d", &count);
    for (i = 0; i < count; ++i)
    {
        if (pop(&stack, &value))
        {            
            printf("出栈: %3d\n", value);
            continue;
        }
        printf("已到栈底, 出栈失败!!!\n");
    }
   
    // 遍历
    traverse(&stack);

    // 清空
    clear(&stack);
    traverse(&stack);


    return 0;
}

void initStack(PSTACK pStack)
{   
    // "头结点"
    pStack->pBottom = (PNODE) malloc( sizeof(NODE) ); 
    checkMemoryAllocat(pStack->pBottom);

    pStack->pBottom->pNext = NULL;  // "头结点"指针域与空

    // 栈底指针 和 栈顶指针 都指向 "头结点"
    pStack->pTop = pStack->pBottom;
    return;
}

// 压栈
void push(PSTACK pStack, int value)
{
    // 新结点
    PNODE pNew = (PNODE) malloc( sizeof(NODE) );
    checkMemoryAllocat(pNew);
    pNew->data = value;

    pNew->pNext = pStack->pTop; // 新结点的指针域 指向 栈顶
    pStack->pTop = pNew; // 栈顶 上移, 指向 新结点

    return;
}

// 遍历
void traverse(PSTACK pStack)
{
    printf("遍历-由顶到底:\n");
    PNODE p = pStack->pTop;

    for (; p != pStack->pBottom; p = p->pNext)
    {
        printf("%3d\n", p->data);
    }

    return;
}

// 弹栈
bool pop(PSTACK pStack, int * pValue)
{   
    if ( isEmpty(pStack) )
    {
        return false;
    }    
    
    PNODE pTemp = pStack->pTop;     // 指向要删除的结点

    *pValue = pTemp->data;          // 记录删除结点的数据域
    
    pStack->pTop = pTemp->pNext;    // 栈顶指针 下移
    
    free(pTemp);    // 释放删除的结点
    pTemp = NULL;

    return true;
}

void checkMemoryAllocat(PNODE pNode)
{
    if (NULL == pNode)
    {
        printf("动态内存分配失败,结束程序!");
        exit(-1);
    }
}

// 栈是否为空
bool isEmpty(PSTACK pStack)
{   
    if (pStack->pTop == pStack->pBottom)
    {
        return true;
    }
    return false;
}

// 清空, 删除所有有效数据, 先下移栈顶, 后释放
void clear(PSTACK pStack)
{
    PNODE pTemp = pStack->pTop; // 用于指向要释放的 结点

    // 释放所有 有效结点
    while (pStack->pTop != pStack->pBottom)
    {
        pTemp = pStack->pTop;
        pStack->pTop = pTemp->pNext;    // 栈顶下移
        // 释放 刚才出栈的结点的内存
        free(pTemp);
        pTemp = NULL;
    }

   return;
}

四, 应用

    1, 函数调用
    2, 中断
    3, 表达式求值(操作数栈, 操作符栈)
    4, 内存分配
    5, 缓冲处理
    6, 迷宫

抱歉!评论已关闭.