【数据结构】之栈(C语言描述)

  栈(Stack)是编程中最常用的数据结构之一。

  栈的特点是“后进先出”,就像堆积木一样,堆的时候要一块一块堆到最上面,拆的时候需要从最上面一块一块往下拆。栈的原理也一样,只不过它的操作不叫堆和拆,而是叫入栈(或压栈)和出栈(或弹栈)。栈要求我们只能在栈顶(最上面的元素)处进行增加和删除。

  栈可以用顺序表示法(顺序栈)和链式表示法(链栈)。由于栈只需要在一端增删节点,不需要在中间某处增删节点,因此即使栈在应用中大多数做的是增删操作,顺序栈虽然在增删操作时略微逊色于链栈(因为可能会扩容),但其存储密度要高于链栈,因此二者在性能方面可以说是各有各的好处。

  下面的代码是使用 C语言 描述的链栈的代码。

  栈的头文件 Stack.h 中的代码:

/**
 * 栈(链栈):
 * 本程序中栈的存储方式:栈顶->节点->节点->...->栈底。即:栈顶是第一个元素
 */
#include <Constant.h>

// 栈中存储的数据的类型
typedef int ElemType;

// 栈中的节点的数据结构体
typedef struct StackNode {
    ElemType value;      // 栈节点中存储的数据的值
    struct StackNode* nextNode; // 下一个节点
} StackNode;

// 栈的数据结构体
typedef struct Stack {
    StackNode* data;    // 栈中存储的所有节点
    int length;         // 栈的长度
    StackNode* topNode; // 栈顶元素节点
} Stack;

// 初始化一个空栈
Status initStack(Stack* S) {
    S->data = (StackNode*)malloc(sizeof(StackNode));
    if(S->data == NULL) {
        printf("初始化栈失败!\n");
        return FAILURE;
    }
    S->length = 0;
    S->topNode = NULL;
    return SUCCESS;
}

// 销毁栈
Status destroyStack(Stack* S) {
    StackNode* tmpNode;
    if(S->data == NULL) {
        printf("栈不存在,销毁失败!\n");
        return FAILURE;
    }
    while(S->topNode != NULL && S->topNode != S->data) {
        tmpNode = S->topNode;
        S->topNode = S->topNode->nextNode;
        free(tmpNode);
    }
    S->data = NULL;
    S->length = 0;
    S->topNode = NULL;
    return SUCCESS;
}

// 清空栈
Status clearStack(Stack* S) {
    StackNode* tmpNode;
    if(S->data == NULL) {
        printf("栈不存在,清空失败!\n");
        return FAILURE;
    }
    if(S->topNode == NULL) {
        return SUCCESS;
    }
    while(S->topNode != S->data) {
        tmpNode = S->topNode;
        S->topNode = S->topNode->nextNode;
        free(tmpNode);
    }
    S->topNode = NULL;
    S->length = 0;
    return SUCCESS;
}

// 判断栈是否为空
Status isStackEmpty(Stack* S) {
    if(S->data == NULL) {
        printf("栈不存在!\n");
        exit(1);
    }
    if(S->length == 0) {
        return TRUE;
    }
    return FALSE;
}

// 获取栈中元素的长度
int getStackLength(Stack* S) {
    if(S->data == NULL) {
        printf("栈不存在!\n");
        exit(1);
    }
    return S->length;
}

// 查看栈顶元素的值
ElemType getTopElem(Stack* S) {
    if(S->data == NULL) {
        printf("栈不存在,获取元素失败!\n");
        exit(1);
    }
    if(S->topNode == NULL) {
        printf("栈是空栈,获取元素失败!\n");
        exit(1);
    }
    return S->topNode->value;
}

// 元素入栈
Status push(Stack* S, ElemType e) {
    StackNode* tmpNode;
    if(S->data == NULL) {
        printf("栈不存在,元素入栈失败!\n");
        return FAILURE;
    }
    tmpNode = (StackNode*)malloc(sizeof(StackNode));
    if(tmpNode == NULL) {
        printf("元素入栈失败!\n");
        return FAILURE;
    }
    tmpNode->value = e;
    S->length++;
    if(S->topNode == NULL) {
        S->topNode = tmpNode;
        S->topNode->nextNode = S->data;
        return SUCCESS;
    }
    tmpNode->nextNode = S->topNode;
    S->topNode = tmpNode;
    return SUCCESS;
}

// 元素出栈
StackNode* pop(Stack* S) {
    StackNode* tmpNode;
    if(S->data == NULL) {
        printf("栈不存在,元素出栈失败!\n");
        exit(1);
    }
    if(S->topNode == NULL) {
        printf("栈是空栈,元素出栈失败!\n");
        return NULL;
    }
    tmpNode = S->topNode;
    S->topNode = S->topNode->nextNode;
    if(S->topNode == S->data) {
        S->topNode = NULL;
    }
    tmpNode->nextNode = NULL;
    S->length--;
    return tmpNode;
}

// 遍历栈中的元素
void traverseStack(Stack* S) {
    StackNode* tmpNode;
    if(S->data == NULL) {
        printf("栈不存在,遍历失败!\n");
        exit(1);
    }
    if(S->topNode == NULL) {
        printf("栈是空栈,遍历失败!\n");
        exit(1);
    }
    printf("遍历栈:");
    tmpNode = S->topNode;
    while(tmpNode != S->data) {
        printf("%-4d", tmpNode->value);
        tmpNode = tmpNode->nextNode;
    }
    printf("\n");
}

// 栈的测试函数
int testStack() {
    // 数据声明
    Stack stack;
    StackNode* node;
    int i;
    // 初始化栈
    if(initStack(&stack) == SUCCESS) {
        printf("初始化栈成功!\n");
    }
    // 判断栈是否是空栈
    printf("栈是否为空栈?%s\n", isStackEmpty(&stack) == TRUE ? "" : "");
    // 元素入栈
    for(i = 1; i <= 5; i++) {
        if(push(&stack, i) == SUCCESS) {
            printf("元素%d入栈成功!\n", i);
        }
    }
    // 遍历栈中的元素
    traverseStack(&stack);
    // 元素出栈
    node = pop(&stack);
    if(node != NULL) {
        printf("元素%d成功出栈!\n", node->value);
    }
    // 遍历栈中的元素
    traverseStack(&stack);
    // 查看栈顶元素的值
    printf("栈顶元素的值是:%d\n", getTopElem(&stack));
    // 获取栈的长度
    printf("栈的当前长度:%d\n", getStackLength(&stack));
    // 清空栈
    if(clearStack(&stack) == SUCCESS) {
        printf("清空栈成功!\n");
    }
    // 销毁栈
    if(destroyStack(&stack) == SUCCESS) {
        printf("销毁栈成功!\n");
    }
    return 0;
}

  常量类 Constant.h 中定义了一些常量,其代码如下:

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

#define TRUE 1
#define FALSE 0

#define SUCCESS 1
#define FAILURE 0

typedef int Status;

  主函数所在的文件 main.c 中的代码如下:

#include <Stack.h>

int main() {
    testStack();
    return 0;
}

  运行结果如下:

初始化栈成功!
栈是否为空栈?是
元素1入栈成功!
元素2入栈成功!
元素3入栈成功!
元素4入栈成功!
元素5入栈成功!
遍历栈:5   4   3   2   1
元素5成功出栈!
遍历栈:4   3   2   1
栈顶元素的值是:4
栈的当前长度:4
清空栈成功!
销毁栈成功!

Process returned 0 (0x0)   execution time : 0.016 s
Press any key to continue.

 

posted on 2017-04-05 10:50  ITGungnir  阅读(810)  评论(0编辑  收藏  举报

导航