作者: 和风细羽 | 来源:发表于2018-11-07 23:06 被阅读0次

一、简介

栈是限定仅在表尾进行插入或删除操作的一种后进先出的线性表。

基本操作:初始化栈、判断是否为空栈、入栈、出栈、获取栈顶元素、销毁栈、出栈、获取栈的大小、清空栈。

根据分配的内存空间不同而分为顺序栈和链栈。

二、顺序栈

/* 顺序栈结构。元素存放在连续的内存空间(系统数组)
 
   栈底元素索引为 0。
 */
typedef struct Stack {
    
    int data[MAXSIZE];
    int top;  // 指向栈顶的索引
    
} Stack;

/// 初始化栈
void initStack(Stack * stack)
{
    stack->top = 0;
}

/// 空栈
bool isEmptyStack(Stack * stack)
{
    return stack->top == 0;
}

/// 满栈
bool isFullStack(Stack * stack)
{
    return stack->top == MAXSIZE;
}

/// 入栈
bool inputStack(Stack * stack, int data)
{
    if (isFullStack(stack))
        return NO;
    
    stack->data[stack->top] = data;
    stack->top++;
    
    return YES;
}

/// 出栈
bool outputStack(Stack * stack, int * data)
{
    if (isEmptyStack(stack))
        return NO;
    
    stack->top--;
    *data = stack->data[stack->top];
    
    return YES;
}

/// 打印栈的内容
void printStack(Stack * stack)
{
    if (isEmptyStack(stack))
        return;
    
    int i = stack->top - 1;
    
    while(i > -1) {
        printf("%d\t", stack->data[i]);
        i--;
    }
    
    printf("\r\n");
}

/// 调用
{
    int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
    int i = 0;
    int data = 0;
    Stack stack = { 0 };
    
    initStack(&stack);
    
    for (i = 0; i < sizeof(array)/sizeof(int); i++) {
        inputStack(&stack, array[i]);
    }
    
    printStack(&stack);
    
    outputStack(&stack, &data);
    printf("%d\n", data);
    outputStack(&stack, &data);
    printf("%d\n", data);
    
    printStack(&stack);
    inputStack(&stack, 11);
    inputStack(&stack, 12);
    printStack(&stack);
}

10  9   8   7   6   5   4   3   2   1   
10
9
8   7   6   5   4   3   2   1   
12  11  8   7   6   5   4   3   2   1

三、链栈

链栈
/* 链栈结构。元素存放在非连续内存空间(动态分配的堆上)
 
   栈顶指向链表的头结点,这样能够向下增加、删除结点。如果栈顶指向链表末尾,那么无法找到上一个结点
 */
typedef struct Stack {
    
    int data;
    struct Stack * next;
    
} Stack;

/// 初始化栈
void initStack(Stack * stack)
{
    stack->next = NULL;
}

/// 空栈
bool isEmptyStack(Stack * stack)
{
    return stack->next == NULL;
}

/// 入栈
void inputStack(Stack * stack, int data)
{
    Stack * newNode = (Stack *)malloc(sizeof(Stack));  // 创建新的结点
    newNode->data = data;   // 赋值
    newNode->next = stack->next;  // next 指向之前的"第一个内容结点"
    
    stack->next = newNode;
}

/// 出栈
bool outputStack(Stack * stack, int * data)
{
    if (isEmptyStack(stack))
        return NO;
    
    Stack * node = stack->next;

    if (data != NULL)
        *data = node->data;

    stack->next = node->next;  // 去掉当前的"第一个内容结点"
    
    return YES;
}

/// 获得栈顶内容
int topData(Stack * stack)
{
    if (isEmptyStack(stack))
        return -1;
    
    Stack * node = stack->next;
    return node->data;
}

/// 打印栈的内容
void printStack(Stack * stack)
{
    if (isEmptyStack(stack))
        return;
    
    Stack * node = stack->next;
    
    while(node) {
        printf("%d\t", node->data);
        node = node->next;
    }
    
    printf("\r\n");
}

/// 调用
{
    int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
    int i = 0;
    int data = 0;
    Stack stack = { 0 };
    
    initStack(&stack);
    
    for (i = 0; i < sizeof(array)/sizeof(int); i++) {
        inputStack(&stack, array[i]);
    }
    
    printStack(&stack);
    
    outputStack(&stack, &data);
    printf("%d\n", data);
    outputStack(&stack, &data);
    printf("%d\n", data);
    
    printStack(&stack);
    inputStack(&stack, 11);
    inputStack(&stack, 12);
    printStack(&stack);
}

12  11  10  9   8   7   6   5   4   3   2   1   
12
11
10  9   8   7   6   5   4   3   2   1   
12  11  10  9   8   7   6   5   4   3   2   1

四、字符匹配

/// 获得栈顶内容
char topData(Stack * stack)
{
    if (isEmptyStack(stack))
        return '\0';   // 空字符
    
    Stack * node = stack->next;
    return node->data;
}

/// 左侧符号
bool isLeft(char c)
{
    return (c == '<') || (c == '[') || (c == '(') || (c == '{');
}

/// 右侧符号
bool isRight(char c)
{
    return (c == '>') || (c == ']') || (c == ')') || (c == '}');
}

/// 引号
BOOL isQuot(char c)
{
    return (c == '\'') || (c == '\"');
}

bool isMatch(char left, char right)
{
    return (left == '<' && right == '>')
            || (left == '[' && right == ']')
            || (left == '(' && right == ')')
            || (left == '{' && right == '}')
            || (left == '\'' && right == '\'')
            || (left == '\"' && right == '\"');
}

/// 解析字符串
bool parse(char * string)
{
    Stack stack = { 0 };
    initStack(&stack);
    
    int i = 0;
    bool result = true;
    
    string = (string == NULL) ? "" : string;
    
    while(result && (string[i] != '\0'))
    {
        char c = string[i];
        // 左符号
        if(isLeft(c)) {
            inputStack(&stack, c); // 入栈
        }
        // 右符号
        else if(isRight(c)) {

            // 栈未空 && 与栈顶元素匹配
            if(!isEmptyStack(&stack) && isMatch(topData(&stack), c)){
                outputStack(&stack, NULL);  // 出栈
            }
            else {
                result = false;
            }
        }
        // 引号、双引号
        else if(isQuot(c)) {
            // 栈为空 || 当前符号与栈顶元素不匹配
            if(isEmptyStack(&stack) || !isMatch(topData(&stack), c))
            {
                inputStack(&stack, c); // 入栈
            }
            // 当前元素与栈顶元素匹配
            else if(isMatch(topData(&stack), c))
            {
                outputStack(&stack, NULL);  // 出栈
            }
        }
        i++;
    }
    return result && isEmptyStack(&stack);
}

/// 调用
{
    char * s = "'([]){}'""";
    
    if (parse(s)) {
        NSLog(@"配对成功");
    }
    else {
        NSLog(@"配对失败");
    }
}

配对成功

五、栈实现队列

static Stack stack_in  = {0};  // 添加数据的栈
static Stack stack_out = {0};  // 移除数据的栈

// 入队
void inputQueue(char c)
{
    inputStack(&stack_in, c);
}

// 出队
char outputQueue()
{
    // 空队列
    if (isEmptyQueue()) {
        printf("空队列\t");
        return '\0';
    }
    
    // out 栈为空
    if (isEmptyStack(&stack_out)) {
        while (!isEmptyStack(&stack_in)) {
            inputStack(&stack_out, topData(&stack_in));
            outputStack(&stack_in, NULL);
        }
    }
    // out 栈为空
    if (isEmptyStack(&stack_out))
        return '\0';
    
    char data;
    outputStack(&stack_out, &data);
    return data;
}

// 空队列
bool isEmptyQueue()
{
    return isEmptyStack(&stack_in) && isEmptyStack(&stack_out);
}

/// 调用
{
    char array[10] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' };
    
    int i = 0;
    // 入队
    for (; i < 4; i++) {
        inputQueue(array[i]);
    }
    
    // 出队
    printf("%c\n", outputQueue());
    
    // 入队
    for (; i < 10; i++) {
        inputQueue(array[i]);
    }
    
    // 出队
    for (int j = 0; j < 12; j++) {
        printf("%c\t", outputQueue());
    }
}

a
b   c   d   e   f   g   h   i   j   空队列     空队列     空队列 

六、学习文章

算法爱好者 # 漫画:如何用栈实现队列?

相关文章

  • Java实现栈

    数组栈:压栈、出栈、返回栈顶元素 链式栈:压栈、出栈、返回栈顶元素

  • 数据结构之 栈

    栈结构 链式栈 一.栈结构体 1构建空栈 2栈置空 3判断栈空 4获取栈顶 5入栈 6出栈 7便利栈 二.链式栈 ...

  • 栈和队列

    1、栈 栈是一种先进先出的数据结构。栈顶进栈,栈顶出栈。 数据结构 栈的初始化 进栈 出栈 栈的最小值 2、队列 ...

  • 递归累加数组

    入栈 5入栈 4入栈 3入栈 2入栈 1出栈 [1 0]出栈 [2 1 0]出栈 [3 2 1 0]出栈 [4 3...

  • 栈的逻辑结构和存储结构

    main()进栈s(1)进栈s(0)进栈 s(0)出栈s(1)出栈main()出栈 顺序栈 一个数组 + 指向栈顶...

  • 单调栈 2020-06-12(未经允许,禁止转载)

    1.单调栈 指栈内元素保持单调性的栈结构,分为单调增栈(栈底到栈顶元素递增)和单调减栈(栈底到栈顶元素递减) 2....

  • 链栈的操作

    链栈的定义 链栈的操作 初始化 判断栈空 入栈 出栈

  • 函数调用栈平衡

    栈平衡 栈平衡:函数调用前后的栈顶指针指向的位置不变 内平栈 外平栈 内平栈: 指的是在函数调用返回之前使栈保持...

  • 栈的简单Java实现

    栈栈的特点是先进后出,出栈、入栈都是在栈顶操作。

  • 汇编学习-入栈和出栈

    栈有两个基本的操作:入栈和出栈。入栈就是将一个新的元素放到栈顶,出栈就是从栈顶取出一个元素。栈顶的元素总是最后入栈...

网友评论

      本文标题:

      本文链接:https://www.haomeiwen.com/subject/xlfbxqtx.html