1. 程式人生 > >《資料結構》(C語言版)——棧的應用舉例

《資料結構》(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;
}

相關推薦

資料結構C語言第三 基礎實驗二

1、編寫函式slnklist delx(linklist head, datatype x),刪除不帶頭結點單鏈表head中第一個值為x 的結點。 並構造測試用例進行測試。 2、假設線性表(a1,a2,a3,…an)採用不帶頭結點的單鏈表儲存, 請設計演算法函式linklist reverse1

資料結構C語言第三基礎實驗一

1、基於sequlist.h中定義的順序表,編寫演算法函式reverse(sequence_list *L),實現順序表的就地倒置。 2、編寫一個演算法函式void sprit( sequence_list *L1,sequence_list *L2,sequence_list *L3), 將順

資料結構C語言讀書筆記1(基本概念和術語)

資料: 所有輸入到計算機中,並被計算機程式處理的符號的總稱。 資料元素: 資料的基本單位,在計算機程式中經常被當做一個整體進行考慮和處理 資料物件: 性質相同的資料元素的集合,是資料的一個子集。 資料結構: 相互之間存在一種或多種特定關係的資料元素的集合。這種資料元素之間

資料結構c語言中線性表的單鏈表儲存結構

本文轉自:https://blog.csdn.net/prlhnxx/article/details/79174782 /* run this program using the console pauser or add your own getch, system("pause") or i

關於嚴蔚敏老師《資料結構C語言》書中程式碼的誤解

清華大學嚴蔚敏老師的《資料結構(C語言版)》以其嚴謹被奉為經典,我是從其Pascal版一路追著買到C語言版,一直覺得這本書理論功力深厚,是不可多得的資料結構教材。但其編寫過程中為避免太過拘泥於具體語言細節,使用了ADT描述,具體演算法中使用了偽碼描述,對於新手直接把程式碼原樣照抄是沒法直接在電腦

C語言實現線性表歸併_含原始碼和執行結果_資料結構C語言

採用動態分配順序儲存結構實現 採用單鏈表結構實現 1.採用動態分配實現 #include<stdio.h> #include<stdlib.h> #define LIST_INIT_SIZE 100 #define LISTINCREM

資料結構C++語言附習題解析》電子書下載 -百度網盤 高清PDF格式

       作者:鄧俊輝 出版日期:2013年9月1日 出版社:清華出版社 頁數:514 ISBN:7-302-33064-6 檔案格式:PDF 檔案大小:24.00 MB   &n

資料結構C語言》電子書下載 -百度網盤 高清PDF格式

作者:嚴蔚敏,吳偉民 出版日期:2007-3-1 出版社:清華出版社 頁數:334 ISBN:9787302147510 檔案格式:PDF 檔案大小:28.95 MB 站長推薦 本書的第1章綜述資料、資料結構和抽象資料型別等基本概念;第2章至第7章從抽象資料

XTU資料結構C語言

表示式中的小括號可能出現不匹配的情況,使用者以字串的方式輸入一個表示式,請用棧這種結構對錶達式中小括號的匹配情況進行檢測,輸出檢測結果(匹配還是不匹配)。 #include<stdio.h> #include<stdlib.h> #include<mallo

20150908資料結構C語言演算法時間複雜度問題

1, 演算法複雜度是在《資料結構》這門課程的第一章裡出現的,因為它稍微涉及到一些數學問題,所以很多同學感覺很難,加上這個概念也不是那麼具體,更讓許多同學複習起來無從下手,下面我們就這個問題給各位考生進行分析。 首先了解一下幾個概念。一個是時間複雜度,一個是漸

資料結構C語言

基本概念及術語 資料結構基本概念 1.資料 所有能輸入到計算機中並被程式處理的符號集合。 2.資料元素 資料的基本單位,在計算機程式中通常被作為一個整體考慮和處理。 3.資料項 資料不可分割的最小單位,相當於記錄的”域”或者欄位。 4.資料物件

資料結構C語言-遞迴學習筆記

遞迴,介紹瞭解決某一類問題的思維方式。在一個函式定義中出現了對自己本身的呼叫,稱為直接遞迴。一個函式p的定義中包含了對函式q的呼叫,而q的實現過程中又呼叫了p,即函式呼叫形成了一個環狀呼叫鏈,這種方式稱之為間接遞迴。 一個最簡單遞迴程式設計的例項。 例子1 編寫一個遞迴函式

浙江中醫藥大學-《資料結構C語言-、佇列、串、陣列

ZCMU-Data Structure (C language) Part 1 Stack and Queue 1、棧和佇列也是線性表,特殊性在於棧和佇列的基本操作是線性表操作的子集,是操作受限的線性

資料結構C語言——應用舉例

/* run this program using the console pauser or add your own getch, system("pause") or input loop */ // 用到的庫檔案 #include <stdio.h> /

資料結構C語言實現:判斷兩棵二叉樹是否相等,bug求解

判斷兩棵二叉樹是否相等。 遇到了bug,求大神幫忙!!! C語言原始碼: #include <stdio.h> #include <stdlib.h> #include <malloc.h> #define OK 1 #define

數據結構C語言

info bsp cpp work spa clu 順序 9.png error 首先,學會用Vistual C++創建一個順序表,以及對順序表的基本操作。 (1)新建一個工程 Win30Application (2)新建SeqList.h (3)新建SeqList.

資料結構c語言——鏈儲存結構及實現

鏈棧:就是一種特殊的單鏈表,FILO(先進後出) 通常對於連結串列來說: 1.是不需要頭節點的。 2.基本不存在滿棧的情況,除非記憶體已沒有可用的空間。   不多bibi你們都懂哈,直接上程式碼:  鏈棧結構: typedef struct Stock

資料結構C語言的建立、入、出並進行進位制轉換

十進位制數轉換為八進位制: | N |N div 8(商) | N mod 8(餘數) |1348| 168 | 4 | 168 | 21 | 0

資料結構C語言讀書筆記6:應用之括號匹配的C程式碼實現

括號匹配的演算法思想: 初始化一個空棧,掃描表示式,依次讀入字元,知道掃描完或者出現錯誤匹配。對於讀入的每個字元,分以下情況處理: (1)、如果是‘’(“”或“【”,將其壓入棧。 (2)、如果是“)”,則根據當前棧頂元素的值分情況考慮。若棧頂元素是“(”,則匹配成功,否則為

資料結構——有序連結串列合併C語言

有序連結串列合併 兩個有序的連結串列,要求將其合併為一個連結串列,並且該連結串列保持有序!! 這裡所講的是連結串列升序! 這裡我們的實驗資料,以及思路如圖所示!! 實驗資料: 連結串列1:1, 3, 5, 7 連結串列2:1, 2, 4 ,5