《数据结构》(C语言版)——栈的应用举例

/* run this program using the console pauser or add your own getch, system("pause") or input loop */
// 用到的库文件
#include <stdio.h>  // printf();scanf()
#include <stdlib.h> // exit()
#include <malloc.h> // malloc()
#include <time.h>   // srand((unsigned)time(NULL));
// 函数结果状态代码
#define TRUE    1
#define FALSE   0
#define OK      1
#define ERROR   0
#define INFEASIBLE  -1
#define OVERFLOW    -2
// Status是函数的类型,其值是函数结果状态代码
typedef int Status;
// #define ElemType int  // 也可以用宏定义确定ElemType类型
typedef char SElemType;
// -----栈的链式存储结构-----
typedef struct SNode {
    SElemType data;                 // 数据域
    struct SNode *next;             // 指针域
} SNode, *LinkStack;

// 操作结果:构造一个空栈S。
Status InitStack(LinkStack &S) {
    S = (LinkStack)malloc(sizeof(SNode));
    if(!S)                          // 存储分配失败
        exit(OVERFLOW);             // exit(-2)程序异常退出
    S->next = NULL;
    S->data = NULL;
    return OK;
}// InitStack

// 操作结果:销毁栈S,S不再存在。
Status DestroyStack(LinkStack &S) {
    LinkStack p = S->next, ptmp;    // p指向栈顶
    while(p) {                      // p指向栈底时,循环停止
        ptmp = p->next;
        free(p);                    // 释放每个数据结点的指针域
        p = ptmp;
    }
    free(S);
    return OK;
}// DestroyStack

// 操作结果:把S置为空栈。
Status ClearStack(LinkStack &S) {
    LinkStack p = S->next, ptmp;    // p指向栈顶
    while(p) {                      // p指向栈底时,循环停止
        ptmp = p->next;
        free(p);                    // 释放每个数据结点的指针域
        p = ptmp;
    }
    S->next = NULL;
    return OK;
}// ClearStack

// 操作结果:若S为空栈,返回TRUE,否则返回FALSE
Status StackEmpty(LinkStack S) {
    if(S->next == NULL)
        return TRUE;                // 返回1
    else
        return FALSE;               // 返回0
}// StackEmpty

// 操作结果:返回S的元素个数,即栈的长度。
int StackLength(LinkStack S) {
    int n = 0;
    LinkStack p = S->next;          // p指向栈顶
    while(p) {
        n++;
        p = p->next;
    }
    return n;
}// StackLength

// 操作结果:若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR。
Status GetTop(LinkStack S, SElemType &e) {
    if ( S->next == NULL )
        return ERROR;               // 栈空
    e = S->next->data;              // 取栈顶元素
//  printf("获取的栈顶元素:%d\n", e);
    return OK;
}// GetTop

// 操作结果:插入元素e为新的栈顶元素。
Status Push(LinkStack &S, SElemType e) {
    LinkStack p = (LinkStack)malloc(sizeof(SNode));
    p->next = S->next;              // 新结点指向栈顶
    p->data = e;
    S->next = p;                    // 更新栈顶指针
//  printf("插入的栈顶元素:%d\n", e);
    return OK;
}// Push

// 操作结果:若栈不空,则删除S的栈顶元素,并用e返回其值;否则返回ERROR。
Status Pop(LinkStack &S, SElemType &e) {
    // 若1个元素也没有:
    if (S->next == NULL)
        return ERROR;
    // 若有1个以上元素
    e = S->next->data;
    LinkStack ptmp = S->next->next;
    free(S->next);
    S->next = ptmp;
//  printf("删除的栈顶元素:%d\n", e);
    return OK;
}// Pop

Status visit(SElemType e) {
    printf("%c -> ", e);
    return OK;
}
// 操作结果:从 栈底到栈顶 依次对栈中每个数据元素调用函数visit()。一旦vistit()失败,刚操作失败。
Status StackTraverse(LinkStack S, Status (*pfn_visit)(SElemType)) {
    if(S->next == NULL)
    {
        printf("栈为空!\n");
        return ERROR;
    }
    for(int i=StackLength(S); i>0; i--)
    {
        LinkStack p = S->next;      // p指向栈顶
        int j = 1;                  // j为计数器
        while ( p && j<i ) {        // 顺指针向后查找,直到p指向第i个元素或p为空
            p = p->next;
            ++j;
        }
        visit(p->data);
    }
    printf("\n");
    return OK;
}// StackTraverse_base_to_Top
// 操作结果:从 栈顶到栈底 依次对栈中每个数据元素调用函数visit()。一旦vistit()失败,刚操作失败。
Status StackTraverse_Top(LinkStack S, Status (*pfn_visit)(SElemType)) {
    if(S->next == NULL)
    {
        printf("栈为空!\n");
        return ERROR;
    }
    LinkStack p = S->next;          // p指向栈顶
    while(p) {
        visit(p->data);
        p = p->next;
    }
    printf("\n");
    return OK;
}// StackTraverse_Top_to_base

// 3.2.1 数制转换
void conversion()
{   // 对于输入的任意一个非负十进制整数,打印输出与其等值的八进制数
    unsigned N = 0;                 // 非负整数
    SElemType e;

    LinkStack S = NULL;
    InitStack(S);                   // 初始化栈

    printf("将十进制整数N转换为8进制数:", N);
    //scanf("%u", &N);
    N = 8;
    while(N)
    {
        Push(S, N % 8);             // 入栈
        N = N/8;
    }
    while(!StackEmpty(S))
    {
        Pop(S, e);                  // 出栈
        printf("%d ", e);
    }
    printf("\n");

    DestroyStack(S);                // 销毁栈
}// conversion 算法3.1

// 3.2.2 括号匹配的检验
void check()
{   // 检验表达式中括号<>、()、[]和{}是否配对
    SElemType e;
    int i = 0;

    LinkStack S;
    InitStack(S);


    const char* expression
        = "#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; }";
    //gets(expression);
    while (expression[i] != '\0')
    {
        switch (expression[i])
        {
        case '<':
        case '(':
        case '[':
        case '{':
            Push(S, expression[i]); // 当遇见左符号时压入栈中
            break;
        case '>':
        case ')':
        case ']':
        case '}':
            if (!StackEmpty(S))     // 当遇见右符号时从栈中弹出栈顶符号 // 进行匹配
            {
                Pop(S, e);
                // 匹配成功:继续读入下一个字符   // 匹配失败:立即停止,并报错
                if ( !( e == '<' && expression[i] == '>' ||
                        e == '(' && expression[i] == ')' ||
                        e == '[' && expression[i] == ']' ||
                        e == '{' && expression[i] == '}' ) )
                {
                    printf("%c does not match!\n", expression[i]);
                    exit(ERROR);
                }
            }
            else
            {
                printf("%c does not match!\n", expression[i]);
                exit(ERROR);
            }
        default:                    // 当遇见普通字符时忽略
            break;
        }
        i++;
    }

    if (StackEmpty(S))              // 成功:所有字符扫描完毕,且栈为空
        printf("Succeed!\n");
    else                            // 失败:匹配失败或所有字符扫描完结但栈非空
        printf("Invalid code!\n");

    DestroyStack(S);
}

//3.2.3 行编辑程序
FILE *fp;
Status copy(SElemType e)    // 将字符e输入至fp所指的文件中
{
    fputc(e, fp);
    return OK;
}
void LineEdit()
{   printf("利用字符栈s,从终端接收一行并送至调用过程的数据区。\n");
    LinkStack S;
    InitStack(S);

    char ch = getchar();                // 从终端接收第一个字符
    while(ch != EOF)                    // EOF为全文结束符
    {
        while(ch != EOF && ch != '\n')
        {
            switch(ch)
            {
            case '#':
                if(!StackEmpty(S))
                    Pop(S, ch);         // 仅当栈非空时退栈
                break;
            case '@':
                ClearStack(S);          // 重置s为空栈
                break;
            default :
                Push(S, ch);            // 有效字符进栈,未考虑栈满情形
                break;
            }
            ch = getchar();             // 从终端接收下一个字符
        }
        // 将从栈底到栈顶的栈内字符传送至调用过程的数据区;
        StackTraverse(S, copy);
        fputc('\n', fp);                // 向文件输入一个换行符

        ClearStack(S);                  // 重置s为空栈

        if(ch != EOF)   ch = getchar();
    }

    DestroyStack(S);
}// LineEdit 算法3.2
int main() {
    conversion();
    check();

    fp = fopen("test.txt", "w");
    if(fp)
    {
        LineEdit();
        fclose(fp);
    }
    else
        printf("建立文件失败!\n");

    return 0;
}

  • 0
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值