利用栈实现的经典案例

本文介绍了如何利用栈来实现三个经典案例:任意进制转换、中缀表达式转后缀表达式并进行计算,以及括号符号的匹配。通过linklist和linkstack的数据结构,实现了相关功能,强调思路的重要性。
摘要由CSDN通过智能技术生成

1.用栈来实现任意进制进制转换

//linklist.h

#ifndef __LINKLIST_H__
#define __LINKLIST_H__

typedef struct linklistnode         
{
    struct linklistnode *next;      
    int item;
}LinkListNode;             //数据节点 

typedef struct linklist         
{
    LinkListNode header;        
    int length;

}LinkList;               //头节点   

LinkList *LinkList_Create();
void LinkList_Destroy(LinkList *list);
void LinkList_Clear(LinkList *list);
int LinkList_Length(LinkList *list);
int LinkList_Insert(LinkList *list, LinkListNode *node, int pos);
LinkListNode *LinkList_Get(LinkList *list,int pos);
LinkListNode *LinkList_Delete(LinkList *list,int pos);

#endif  //__LINKLIST_H__

//linklist.c

#include <stdlib.h>

#include "linklist.h"


LinkList *LinkList_Create()
{
    LinkList *ret = NULL;

    ret = malloc(sizeof(LinkList));

    if(ret!=NULL)
    {
        ret->length = 0;
        ret->header.next = NULL;
    }

    return ret;
}

void LinkList_Destroy(LinkList *list)
{
    free(list);
}

void LinkList_Clear(LinkList *list)
{
    if(list!=NULL)
    {
        list->length =0;
        list->header.next = NULL;
    }
}

int LinkList_Length(LinkList *list)
{
    int ret = -1;

    if( list!=NULL )
    {
        ret = list->length; 
    }

    return ret;
}

int LinkList_Insert(LinkList *list, LinkListNode *node, int pos)
{
    int ret = list!=NULL && node!=NULL && pos>=0;

    if( ret )
    {
        int i;
        LinkListNode *cur = (LinkListNode *)list;

        for(i=0;i<pos && cur->next!=NULL;i++)
        {
            cur = cur->next; 
        }
        node->next = cur->next;
        cur->next = node;
        list->length++;
    }

    return ret;
}

LinkListNode *LinkList_Get(LinkList *list,int pos)
{
    LinkListNode *ret = NULL;

    if( list!=NULL && (0<=pos && pos<list->length) )
    {
        int i;
        LinkListNode *cur = (LinkListNode *)list;

        for(i=0; i<pos; i++)
            cur = cur->next;
        ret = cur->next;        //因为从0开始计数的,要第三个数,那么就是第二个数的next
    }

    return ret;
}

LinkListNode *LinkList_Delete(LinkList *list,int pos)
{
    LinkListNode *ret = NULL;

    if(list!=NULL && (0<=pos&&pos<list->length) )
    {
        int i;
        LinkListNode *cur = (LinkListNode *)list;

        for(i=0; i<pos; i++)
            cur = cur->next;
        ret = cur->next;    //单项链表是从0开始排的。
        cur->next = ret->next;
        list->length--;
    }

    return ret;
}

//linkstack.h

#ifndef __LINKSTACK_H__
#define __LINKSTACK_H__


typedef struct linkstacknode
{
    struct linkstacknode *node;
    void *item;
}LinkStackNode;

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_H__

//linkstack.c

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

#include "linklist.h"
#include "linkstack.h"


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)
{
    LinkStackNode *node = malloc(sizeof(LinkStackNode));
    int ret = stack!=NULL && item!=NULL && node!=NULL;

    if( ret )
    {
        memset(node,0x00,sizeof(*node)); //?? 
        node->item = item;
        ret = LinkList_Insert(stack, (LinkListNode *)node, 0);
    }

    if(!ret)
    {
        free(node);
    }

    return ret;
}

void *LinkStack_Pop(LinkStack *stack)
{
    LinkStackNode *node = NULL;
    void *ret = NULL;

    node = (LinkStackNode *)LinkList_Delete(stack,0);

    if ( node != NULL)
    {
        ret = node->item;
        free(node);
    }

    return ret;
}

void *LinkStack_Top(LinkStack *stack)
{
    LinkStackNode *node = NULL;
    void *ret = NULL;

    node = (LinkStackNode *)LinkList_Get(stack,0);

    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"


void convert(int digit,int base)
{
    static char num[]= {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};

    LinkStack *stack = LinkStack_Create();

    do
    {
        LinkStack_Push(stack,&num[digit%base]); //进栈
        digit /= base;

    }while( digit!= 0 );

    while ( LinkStack_Size(stack) > 0 )
    {
        char *c = (char *)LinkStack_Pop(stack); //出栈
        printf("%c", *c);
    }
    printf("\n");

    LinkStack_Destroy(stack);
}

int main( void )
{
    convert(10,2);  //十进制的10转换为2进制

    convert(32,16);  //十进制的转换为16进制 

    return 0;
}

Makefile


cc :=gcc

main : main.o linklist.o linkstack.o
    gcc $^ -o $@


.PHONY : main clean

clean:
    rm -rf *.o main

2.用栈来实现加、减、乘、除的计算

中缀转后缀

对于数字,直接输出
    对于符号:
        左括号:进栈
        符号:于栈顶符号进行优先级比较
        栈顶优先级低:进栈
        栈顶优先级不低,将栈顶符号弹出并输出,之后进栈
        右括号:将栈顶符号弹出并输出,知道匹配左括号

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

后缀表达式计算:

对于数字:进栈
对于符号:
    从栈中弹出右右操作数
    从栈中弹出左操作数
    根据运算符进行运算
    将运算结果入栈
遍历结束:栈中唯一数字就是运算结果

有时候代码不重用,重要的是我们的思路,当我们有思路,那么我们剩下的就是把我们向的变为代码就ok了

//linklist.h

#ifndef __LINKLIST_H__
#define __LINKLIST_H__

typedef struct linklistnode         
{
    struct linklistnode *next;      
    int item;
}LinkListNode;             //数据节点 

typedef struct linklist         
{
    LinkListNode header;        
    int length;

}LinkList;               //头节点   

LinkList *LinkList_Create();
void LinkList_Destroy(LinkList *list);
void LinkList_Clear(LinkList *list);
int LinkList_Length(LinkList *list);
int LinkList_Insert(LinkList *list, LinkListNode *node, int pos);
LinkListNode *LinkList_Get(LinkList *list,int pos);
LinkListNode *LinkList_Delete(LinkList *list,int pos);

#endif  //__LINKLIST_H__

//linklist.c

#include <stdlib.h>

#include "linklist.h"


LinkList *LinkList_Create()
{
    LinkList *ret = NULL;

    ret = malloc(sizeof(LinkList));

    if(ret!=NULL)
    {
        ret->length = 0;
        ret->header.next = NULL;
    }

    return ret;
}

void LinkList_Destroy(LinkList *list)
{
    free(list);
}

void LinkList_Clear(LinkList *list)
{
    if(list!=NULL)
    {
        list->length =0;
        list->header.next = NULL;
    }
}

int LinkList_Length(LinkList *list)
{
    int ret = -1;

    if( list!=NULL )
    {
        ret = list->length; 
    }

    return ret;
}

int LinkList_Insert(LinkList *list, LinkListNode *node, int pos)
{
    int ret = list!=NULL && node!=NULL && pos>=0;

    if( ret )
    {
        int i;
        LinkListNode *cur = (LinkListNode *)list;

        for(i=0;i<pos && cur->next!=NULL;i++)
        {
            cur = cur->next; 
        }
        node->next = cur->next;
        cur->next = node;
        list->length++;
    }

    return ret;
}

LinkListNode *LinkList_Get(LinkList *list,int pos)
{
    LinkListNode *ret = NULL;

    if( list!=NULL && (0<=pos && pos<list->length) )
    {
        int i;
        LinkListNode *cur = (LinkListNode *)list;

        for(i=0; i<pos; i++)
            cur = cur->next;
        ret = cur->next;        //因为从0开始计数的,要第三个数,那么就是第二个数的next
    }

    return ret;
}

LinkListNode *LinkList_Delete(LinkList *list,int pos)
{
    LinkListNode *ret = NULL;

    if(list!=NULL && (0<=pos&&pos<list->length) )
    {
        int i;
        LinkListNode *cur = (LinkListNode *)list;

        for(i=0; i<pos; i++)
            cur = cur->next;
        ret = cur->next;    //单项链表是从0开始排的。
        cur->next = ret->next;
        list->length--;
    }

    return ret;
}

//linkstack.h

#ifndef __LINKSTACK_H__
#define __LINKSTACK_H__


typedef struct linkstacknode
{
    struct linkstacknode *node;
    void *item;
}LinkStackNode;

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_H__

//linkstack.c

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

#include "linklist.h"
#include "linkstack.h"


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)
{
    LinkStackNode *node = malloc(sizeof(LinkStackNode));
    int ret = stack!=NULL && item!=NULL && node!=NULL;

    if( ret )
    {
        memset(node,0x00,sizeof(*node)); //?? 
        node->item = item;
        ret = LinkList_Insert(stack, (LinkListNode *)node, 0);
    }

    if(!ret)
    {
        free(node);
    }

    return ret;
}

void *LinkStack_Pop(LinkStack *stack)
{
    LinkStackNode *node = NULL;
    void *ret = NULL;

    node = (LinkStackNode *)LinkList_Delete(stack,0);

    if ( node != NULL)
    {
        ret = node->item;
        free(node);
    }

    return ret;
}

void *LinkStack_Top(LinkStack *stack)
{
    LinkStackNode *node = NULL;
    void *ret = NULL;

    node = (LinkStackNode *)LinkList_Get(stack,0);

    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 <string.h>
#include <assert.h>

#include "linkstack.h"

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

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

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

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

int priority(char c)
{
    int ret=0;

    if( c=='+' || c=='-' )
        ret = 1;
    if( c=='*' || c=='/' )
        ret = 2;

    return ret;
}

//前缀表达式:
void transfrom( const char *exp, char *buf)
{
    int i = 0;
    int idx = 0;
    LinkStackNode *stack = LinkStack_Create();

    while ( exp[i] != 0 )
    {
        if( isNum(exp[i]))     //是数字,直接输出
        {
            //putchar(exp[i]);
            buf[idx++] = exp[i]; 
        }
        else if( isLeft(exp[i]) )   //是左(就进栈
        {
            LinkStack_Push(stack, ( void * )(int)exp[i]); 
        }
        else if ( isOperator(exp[i]) )  //是运算符,就进行比较优先级
        {
            while(priority(exp[i]) <= priority((char)(int)LinkStack_Top(stack))) 
            {
                //putchar((char)(int)LinkStack_Pop(stack)); //输出栈顶元素
                buf[idx++] = ((char)(int)LinkStack_Pop(stack));
            }
            LinkStack_Push(stack, (void *)(int)exp[i]); //在把它进栈
        }
        else if( isRight(exp[i]) )  //是右) 并且栈顶的不是(,就让他一直输出栈顶元素
        {
            while ( !isLeft( (char)(int)LinkStack_Top(stack) )) 
            {
                //putchar((char)(int)LinkStack_Pop(stack)); 
                buf[idx++] = ((char)(int)LinkStack_Pop(stack)); 
            }
            LinkStack_Pop(stack);   //栈顶是(,则弹出并没有输出
        }
        else
        {
            printf("invalid expresstiom!\n"); 
            break;
        }

        i++;
    }

    while(exp[i]==0 && LinkStack_Size(stack) )  //没有了表达式,并且栈有操作符,就让他直接输入
    {
        //putchar((char)(int)LinkStack_Pop(stack)); 
        buf[idx++] = ((char)(int)LinkStack_Pop(stack)); 
    }
    //putchar('\n');
    buf[idx] = 0;       //加了一个‘\0'

    LinkStack_Destroy(stack);
}


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


int operation(int left,int right, int op)
{
    int ret = 0;

    switch (op)
    {
        case '+':
            ret = left + right;
            break;
        case '-':
            ret = left - right;
            break;
        case '*':
            ret = left * right;
            break;
        case '/':
            assert(right);
            ret = left / right;
            break;
        default:
            printf("error!\n");
            exit(1);
            break;
    }

    return ret;
}


//后缀表达式:
int compute(const char *exp)
{
    int i = 0;
    int res = 0;
    LinkStack *stack = LinkStack_Create();

    while ( exp[i]!= 0 )
    {
        if( isNum(exp[i]) )     //是数字,就进栈
        {
            LinkStack_Push(stack, (void *)value(exp[i])); 
        }
        else if( isOperator(exp[i]) )   //是操作数,就让栈顶两个数出栈,进行运算
        {
            int r = (int)LinkStack_Pop(stack);
            int l = (int)LinkStack_Pop(stack);
            int ret = operation(l,r,exp[i]);
            LinkStack_Push(stack, (void *)ret);
        }
        else
        {
            printf("invalid expression!\n"); 
            break;
        }

        i++;
    }

    if( LinkStack_Size(stack)==1 && exp[i]==0 ) //只有输入一个数的时候,直接让他输出
    {
        res = (int)LinkStack_Pop(stack); 
    }

    LinkStack_Destroy(stack);

    return res;
}


int main( void )
{

    char buf[1024] = {};
    char exp[1024] = {};

//    transfrom("5+3*2");

    while ( 1 )
    {
        printf("输入一个算式表达式:"); 
        fgets(buf, 1024, stdin);    //标准输入放入buf中
        buf[strlen(buf)-1] = 0;     //清掉最后一个换行符
        transfrom(buf, exp);        //表达式通过buf传过去,在通过exp带回来结果,
        printf("%s=", buf);
        printf("%d\n",compute(exp));

    }

//    printf("9-3*2+(5-1)");
//    printf("%d\n",compute("932*-51-+"));
    return 0;
}

//Makefile


cc :=gcc

main : main.o linklist.o linkstack.o
    gcc $^ -o $@


.PHONY : main clean

clean:
    rm -rf *.o main

3.用栈来实现符号的匹配

和上一个的其他函数都一样,就主函数变化为:

//main.c

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

#include "linkstack.h"

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

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

//匹配
int match(char left, char right)
{
    int ret;

    switch (left)
    {
        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 )
{
    int i = 0;
 //   int ret = 0;

    LinkStackNode *stack = LinkStack_Create();

    while ( code[i] !='\0' )
    {
        if( isLeft(code[i]) )
        {
            LinkStack_Push(stack, (void *)(int)code[i]); 
        }
        if( isRight(code[i]))
        {
            char c = (char)(int)LinkStack_Pop(stack);
            if( !match(c, code[i]) )
            {
                printf("%c no matched\n",code[i]); 
                return -1;
           //     break;
            }
        }
        i++;
    }

    if( LinkStack_Size(stack)==0 && code[i]=='\0' )
    {
        printf("success!\n"); 
    }
    else
    {
        printf("invalid!\n");
    }

    LinkStack_Destroy(stack);

    return 0;
//    return ret;
}

*/

int scanner( const char *code )
{
    int i = 0;
    int ret = 0;

    LinkStackNode *stack = LinkStack_Create();

    while ( code[i] !='\0' )
    {
        if( isLeft(code[i]) )
        {
            LinkStack_Push(stack, (void *)(int)code[i]); 
        }
        if( isRight(code[i]))
        {
            char c = (char)(int)LinkStack_Pop(stack);
            if( !match(c, code[i]) )
            {
                printf("%c no matched\n",code[i]); 
                ret = -1;
                break;
            }
        }
        i++;
    }

    if( LinkStack_Size(stack)==0 && code[i]=='\0' )
    {
        printf("success!\n"); 
    }
    else
    {
        printf("invalid!\n");
    }

    LinkStack_Destroy(stack);

    return ret;
}


int main( void )
{
    const char *code = "#include <stdlib.h>"
                        "int main( void )"
                            "}";

    scanner(code);

    return 0;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值