C语言 c++ php mysql nginx linux lnmp lamp lanmp memcache redis 面试 笔记 ppt 设计模式 问题 远程连接

数据结构-线性表-栈

 

栈:后进先出(LIFO) last in first out
栈是一种特殊的线性表,只能在线性表的一端进行操作。
栈顶 top
栈底 bottom

实现方式:顺序结构实现,线性结构实现

 

链式存储实现

LinkStack.h

#ifndef _LINKSTACK_H_
#define _LINKSTACK_H_

typedef void LinkStack;

LinkStack* LinkStack_Create();

void LinkStack_Destroy(LinkStack* stack);

void LinkStack_Clear(LinkStack* stack);

int LinkStack_Push(LinkStack* stack, void* item);

void* LinkStack_Pop(LinkStack* stack);

void* LinkStack_Top(LinkStack* stack);

int LinkStack_Size(LinkStack* stack);

#endif

LinkStack.c

#include <malloc.h>
#include "LinkStack.h"
#include "LinkList.h"

typedef struct _tag_LinkStackNode
{
    LinkListNode header;
    void* item;
} TLinkStackNode;

LinkStack* LinkStack_Create()
{
    return LinkList_Create();
}

void LinkStack_Destroy(LinkStack* stack)
{
    LinkStack_Clear(stack);
    LinkList_Destroy(stack);
}

void LinkStack_Clear(LinkStack* stack)
{
    while( LinkStack_Size(stack) > 0 )
    {
        LinkStack_Pop(stack);
    }
}

int LinkStack_Push(LinkStack* stack, void* item)
{
    TLinkStackNode* node = (TLinkStackNode*)malloc(sizeof(TLinkStackNode));
    int ret = (node != NULL) && (item != NULL);
    
    if( ret )
    {
        node->item = item;
        
        ret  = LinkList_Insert(stack, (LinkListNode*)node, 0);
    }
    
    if( !ret )
    {
        free(node);
    }
    
    return ret;
}

void* LinkStack_Pop(LinkStack* stack)
{
    TLinkStackNode* node = (TLinkStackNode*)LinkList_Delete(stack, 0);
    void* ret = NULL;
    
    if( node != NULL )
    {
        ret = node->item;
        
        free(node);
    }
    
    return ret;
}

void* LinkStack_Top(LinkStack* stack)
{
    TLinkStackNode* node = (TLinkStackNode*)LinkList_Get(stack, 0);
    void* ret = NULL;
    
    if( node != NULL )
    {
        ret = node->item;
    }
    
    return ret;
}

int LinkStack_Size(LinkStack* stack)
{
    return LinkList_Length(stack);
}

main.c

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

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char *argv[]) 
{
    LinkStack* stack = LinkStack_Create();
    int a[10];
    int i = 0;
    
    for(i=0; i<10; i++)
    {
        a[i] = i;
        
        LinkStack_Push(stack, a + i);
    }
    
    printf("Top: %d\n", *(int*)LinkStack_Top(stack));
    printf("Length: %d\n", LinkStack_Size(stack));
    
    while( LinkStack_Size(stack) > 0 )
    {
        printf("Pop: %d\n", *(int*)LinkStack_Pop(stack));
    }
    
    LinkStack_Destroy(stack);
    
    return 0;
}

 

顺序存储实现:

SeqStack.h

#ifndef _SEQSTACK_H_
#define _SEQSTACK_H_

typedef void SeqStack;

SeqStack* SeqStack_Create(int capacity);

void SeqStack_Destroy(SeqStack* stack);

void SeqStack_Clear(SeqStack* stack);

int SeqStack_Push(SeqStack* stack, void* item);

void* SeqStack_Pop(SeqStack* stack);

void* SeqStack_Top(SeqStack* stack);

int SeqStack_Size(SeqStack* stack);

int SeqStack_Capacity(SeqStack* stack);

#endif

SeqStack.c

#include "SeqStack.h"
#include "SeqList.h"

SeqStack* SeqStack_Create(int capacity)
{
    return SeqList_Create(capacity);
}

void SeqStack_Destroy(SeqStack* stack)
{
    SeqList_Destroy(stack);
}

void SeqStack_Clear(SeqStack* stack)
{
    SeqList_Clear(stack);
}

int SeqStack_Push(SeqStack* stack, void* item)
{
    return SeqList_Insert(stack, item, SeqList_Length(stack));
}

void* SeqStack_Pop(SeqStack* stack)
{
    return SeqList_Delete(stack, SeqList_Length(stack) - 1);
}

void* SeqStack_Top(SeqStack* stack)
{
    return SeqList_Get(stack, SeqList_Length(stack) - 1);
}

int SeqStack_Size(SeqStack* stack)
{
    return SeqList_Length(stack);
}

int SeqStack_Capacity(SeqStack* stack)
{
    return SeqList_Capacity(stack);
}

main.c

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

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char *argv[]) 
{
    SeqStack* stack = SeqStack_Create(20);
    int a[10];
    int i = 0;
    
    for(i=0; i<10; i++)
    {
        a[i] = i;
        
        SeqStack_Push(stack, a + i);
    }
    
    printf("Top: %d\n", *(int*)SeqStack_Top(stack));
    printf("Capacity: %d\n", SeqStack_Capacity(stack));
    printf("Length: %d\n", SeqStack_Size(stack));
    
    while( SeqStack_Size(stack) > 0 )
    {
        printf("Pop: %d\n", *(int*)SeqStack_Pop(stack));
    }
    
    SeqStack_Destroy(stack);
    
    return 0;
}

 

栈的特别实现

  q1是专职进出栈的,q2只是个中转站。元素集中存放在一个栈中(q1 或 q2, 会根据不同情况变动)

  定义两个指针:pushtmp:指向专门进栈的队列q1; tmp:指向临时作为中转站的另一个栈q2

  入栈:直接入pushtmp所指队列即可
  出栈:把pushtmp的除最后一个元素外全部转移到队列tmp中,然后把刚才剩下q1中的那个元素出队列

参考:http://www.cnblogs.com/kaituorensheng/archive/2013/03/02/2939690.html  

 

栈的应用:

互不相邻,又相互匹配的事物
非常适合于就近匹配的场合

1、检测代码中括号是否匹配

  原理:

 

1、从左往右扫描

2、遇到普通字符忽略,遇到做符号入栈

3、遇到有符号出栈

4、进行匹配

匹配成功继续下一个

匹配失败,停止报错

5、结束

成功:所有字符扫描完毕,且栈为空

失败:匹配失败或扫描完毕栈不为空

 

 

检测括号是否匹配

main.c

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

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int isLeft(char c)
{
    int ret = 0;
    
    switch(c)
    {
        case '<':
        case '(':
        case '[':
        case '{':
        case '\'':
        case '\"':
            ret = 1;
            break;
        default:
            ret = 0;
            break;
    }
    
    return ret;
}

int isRight(char c)
{
    int ret = 0;
    
    switch(c)
    {
        case '>':
        case ')':
        case ']':
        case '}':
        case '\'':
        case '\"':
            ret = 1;
            break;
        default:
            ret = 0;
            break;
    }
    
    return ret;
}

int match(char left, char right)
{
    int ret = 0;
    
    switch(left)
    {
        case '<':
            ret = (right == '>');
            break;
        case '(':
            ret = (right == ')');
            break;
        case '[':
            ret = (right == ']');
            break;
        case '{':
            ret = (right == '}');
            break;
        case '\'':
            ret = (right == '\'');
            break;
        case '\"':
            ret = (right == '\"');
            break;
        default:
            ret = 0;
            break;
    }
    
    return ret;
}

int scanner(const char* code)
{
    LinkStack* stack = LinkStack_Create();
    int ret = 0;
    int i = 0;
    
    while( code[i] != '\0' )
    {
        if( isLeft(code[i]) )
        {
            LinkStack_Push(stack, (void*)(code + i));
        }
        
        if( isRight(code[i]) )
        {
            char* c = (char*)LinkStack_Pop(stack);
            
            if( (c == NULL) || !match(*c, code[i]) )
            {
                printf("%c does not match!\n", code[i]);
                ret = 0;
                break;
            }
        }
        
        i++;
    }
    
    if( (LinkStack_Size(stack) == 0) && (code[i] == '\0') )
    {
        printf("Succeed!\n");
        ret = 1;
    }
    else
    {
        printf("Invalid code!\n");
        ret = 0;
    }
    
    LinkStack_Destroy(stack);
    
    return ret;
}

int main(int argc, char *argv[])
{
    const char* code = "#include <stdio.h> int main() { int a[5][5]; int (*p)[4]; p = a[0]; printf(\"%d\\n\", &p[3][3] - &a[3][3]); return 0; }";
    
    scanner(code);
    
    return 0;
}

 

2、计算机做数学运算

中缀表达式符合我们的阅读习惯
后缀表达式符合计算机运算习惯

中缀转后缀计算方式:

  遍历中缀表达式中的数字和符号

  对于数字:直接输出

  对于符号:

    左括号:进栈

    符号:与栈顶符号进行优先级比较

       栈顶符号优先级低:入栈

       其他情况(高于或等于,括号和栈为空认为最低):将栈顶符号弹出直至为空或比当前符号优先级低,然后入栈

    右括号:将栈顶符号弹出直至匹配左括号

  遍历结束:将栈中所有符号弹出

 

中缀转后缀: 

#include <stdio.h>
#include "LinkStack.h"

int isNumber(char c)
{
    return ('0' <= c) && (c <= '9');
}

int isOperator(char c)
{
    return (c == '+') || (c == '-') || (c == '*') || (c == '/');
}

int isLeft(char c)
{
    return (c == '(');
}

int isRight(char c)
{
    return (c == ')');
}

int priority(char c)
{
    int ret = 0;
    
    if( (c == '+') || (c == '-') )
    {
        ret = 1;
    }
    
    if( (c == '*') || (c == '/') )
    {
        ret = 2;
    }
    
    return ret;
}

void output(char c)
{
    if( c != '\0' )
    {
        printf("%c", c);
    }
}

void transform(const char* exp)
{
    LinkStack* stack = LinkStack_Create();
    int i = 0;
    
    while( exp[i] != '\0' )
    {
        if( isNumber(exp[i]) )
        {
            output(exp[i]);
        }
        else if( isOperator(exp[i]) )
        {
            //栈顶比他低则入栈,高则先把栈里面依次出栈后在入栈
            while( priority(exp[i]) <= priority((char)(int)LinkStack_Top(stack)) )
            {
                output((char)(int)LinkStack_Pop(stack));
            }
            
            LinkStack_Push(stack, (void*)(int)exp[i]);
        } 
        else if( isLeft(exp[i]) )
        {
            LinkStack_Push(stack, (void*)(int)exp[i]);
        } 
        else if( isRight(exp[i]) )
        {
            char c = '\0';
            
            while( !isLeft((char)(int)LinkStack_Top(stack)) )
            {
                output((char)(int)LinkStack_Pop(stack));
            }
            
            LinkStack_Pop(stack);
        }
        else
        {
            printf("Invalid expression!");
            break;
        }
        
        i++;
    }
    
    while( (LinkStack_Size(stack) > 0) && (exp[i] == '\0') )
    {
        output((char)(int)LinkStack_Pop(stack));
    }
    
    LinkStack_Destroy(stack);
}

int main()
{
    transform("9+(3-1)*5+8/2");
    
    printf("\n");
    
    return 0;
}

 

后缀计算:

#include <stdio.h>
#include "LinkStack.h"

int isNumber(char c)
{
    return ('0' <= c) && (c <= '9');
}

int isOperator(char c)
{
    return (c == '+') || (c == '-') || (c == '*') || (c == '/');
}

int value(char c)
{
    return (c - '0');
}

int express(int left, int right, char op)
{
    int ret = 0;
    
    switch(op)
    {
        case '+':
            ret = left + right;
            break;
        case '-':
            ret = left - right;
            break;
        case '*':
            ret = left * right;
            break;
        case '/':
            ret = left / right;
            break;
        default:
            break;
    }
    
    return ret;
}

int compute(const char* exp)
{
    LinkStack* stack = LinkStack_Create();
    int ret = 0;
    int i = 0;
    
    while( exp[i] != '\0' )
    {
        if( isNumber(exp[i]) )
        {
            LinkStack_Push(stack, (void*)value(exp[i]));
        }
        else if( isOperator(exp[i]) )
        {
            int right = (int)LinkStack_Pop(stack);
            int left = (int)LinkStack_Pop(stack);
            int result = express(left, right, exp[i]);
            
            LinkStack_Push(stack, (void*)result);
        }
        else
        {
            printf("Invalid expression!");
            break;
        }
        
        i++;
    }
    
    if( (LinkStack_Size(stack) == 1) && (exp[i] == '\0') )
    {
        ret = (int)LinkStack_Pop(stack);
    } 
    else 
    {
        printf("Invalid expression!");
    }
    
    LinkStack_Destroy(stack);
    
    return ret;
}

int main()
{
    printf("9 + (3 - 1) * 5 + 8 / 2 = %d\n", compute("931-5*+82/+"));
    
    return 0;
}

 

3、进制转换

4、迷宫问题

  http://www.cnblogs.com/liuling/archive/2013/04/29/mazestack.html

5、历史记录

 6、汉诺塔

posted on 2015-09-20 11:32  思齐_  阅读(484)  评论(0编辑  收藏  举报