數據結構編程筆記八:第三章 棧和隊列 順序棧和進位製程序的實現

這次我們一起看看一種特殊的線性表——棧的順序存儲結構實現。

還是老規矩:

程序在碼雲上可以下載。
地址:https://git.oschina.net/601345138/DataStructureCLanguage.git

棧是一個被限制了插入和刪除操作發生位置的線性表。棧的插入和刪除操作只能發生在線性表一端,這個位置稱之爲棧頂,與之相反的另一端稱之爲棧底。棧不允許從棧頂和棧底中間的任意位置插入和刪除元素。這樣的操作限制導致棧具備了“先進後出,後進先出”(FIFO)的特性。這也使得棧的可以執行的操作不像線性表那麼多,那麼隨意了。

還要向大家強調一點:棧和隊列是非常重要的兩種數據結構,我們在後期的程序中會經常把棧和隊列引入,作爲一種工具來使用。比如:二叉樹先序、中序、後續的非遞歸遍歷,圖的深度優先和廣度優先遍歷都會涉及到這兩種數據結構中的一種,所以請大家一定親自動手做一下棧和隊列的程序,這對後期程序的理解和實現是有幫助的。

在計算機中,函數調用的過程必然會涉及到棧。細心的童鞋會發現,無論是嵌套調用還是遞歸調用,函數調用的順序非常符合“先進後出”的特徵。每調用一個函數,就要在運行時棧中壓入這個函數的信息(包括實參和返回值)(壓棧),函數運行結束後,這個函數的信息會從棧中彈出(彈棧)。非常像計算機中的一個概念“中斷”。理解運行時棧的這一特性有利於理解函數遞歸調用的整個過程,也就會明白遞歸算法的效率爲什麼會比非遞歸的差了。這對於後期理解二叉樹先序、中序、後續的遞歸遍歷算法的執行過程有好處。好多老師講課根本不會講到這一知識點,這個知識點在書上56頁有詳細說明。很多時候程序運行發生了棧溢出(Java語言中的StackOverflowException),你就該明白那是什麼意思了。

首先來看看棧的抽象數據類型定義:

ADT Stack{
  數據對象:D ={ai | ai∈Elemset,(i=1,2,…,n, n≥0)}
  數據關係:R1 = {<ai-1,ai>|ai-1,ai ∈ D,(i=2,3,…,n)}    
                 約定an爲棧頂, a1爲棧底。
  基本操作:
       InitStack(&S)
          操作結果:構造一個空的棧S。
       DestroyStack(&S)
          初始條件: 棧S已經存在。
          操作結果: 銷燬棧S。
       ClearStack(&S)
          初始條件: 棧S已經存在。
          操作結果: 將棧S重置爲空棧。
       StackIsEmpty(S)
          初始條件: 棧S已經存在。
          操作結果: 若棧S爲空棧,則返回TURE;否則返回FALSE。
       StackLength(S)
          初始條件: 棧S已經存在。
          操作結果: 返回棧S中的數據元素個數。
       GetTop(S, &e)
          初始條件: 棧S已經存在且非空。
          操作結果: 用e返回棧S中棧頂元素的值。
       Push(&S, e)       //入棧操作
          初始條件: 棧S已經存在。
          操作結果: 插入元素e爲新的棧頂元素。
       Pop(&S, &e)       //出棧操作
          初始條件: 棧S已經存在且非空。
          操作結果: 刪除S的棧頂元素並用e返回其值。
       StackTraverse(S, visit ())
          初始條件: 棧S已經存在且非空。
          操作結果: 從棧底到棧頂依次對S的每個元素調用函數visit ()。一旦visit ()失敗,則操作失敗。      
}ADT Stack

一起來看看程序的實現。

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>引入頭文件<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

#include <stdio.h>   //使用了標準庫函數 
#include <stdlib.h>  //使用了動態內存分配函數 

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>自定義符號常量<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 

#define STACK_INIT_SIZE 100  //存儲空間初始分配量 
#define STACKINCREMENT 10    //存儲空間分配增量 
#define OVERFLOW -2         //內存溢出錯誤常量
#define OK 1                //表示操作正確的常量 
#define ERROR 0             //表示操作錯誤的常量

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>自定義數據類型<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

typedef int Status;       //用typedef給int起個別名,也便於程序的維護 
typedef int SElemType;   //用typedef給int起個別名,也便於程序的維護
typedef struct {     //棧的順序存儲表示 

    SElemType *base;            //棧底指針,在棧構造之前和銷燬之後,base的值爲NULL 
    SElemType *top;             //棧頂指針
    int stacksize;              //當前已分配的存儲空間,以元素爲單位 
}SqStack; 

//-------------------------------------------順序棧的主要操作-----------------------------------------

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>1.初始化順序棧<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 

/*
    函數:InitStack_Sq
    參數:SqStack &S 順序棧引用  
    返回值:狀態碼,OK表示操作成功 
    作用:構造一個空的順序棧 
*/
Status InitStack_Sq(SqStack &S){

    //動態申請順序棧的內存空間,並檢查內存空間是否成功分配
    //if(!(S.base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType))))
    //這句代碼相當於以下兩行代碼:
    //S.base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
    //if(!S.base)  <=>  if(S.base == NULL) 
    if(!(S.base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType)))){
        printf("內存分配失敗,程序即將退出!\n");
        exit(OVERFLOW);
    }//if

    //由於剛動態分配完的棧是空棧,所以棧頂指針和棧底指針都指向棧底   
    S.top = S.base;

    //棧的大小就是棧的初始化大小參數STACK_INIT_SIZE 
    S.stacksize = STACK_INIT_SIZE;

    //操作成功 
    printf("順序棧S所需內存已分配成功!\n");
    return OK; 
}//InitStack_Sq

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>2.銷燬順序棧<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

/*
    函數:DestoryStack_Sq
    參數:SqStack &S 順序棧引用  
    返回值:狀態碼,OK表示操作成功 
    作用:釋放順序棧S所佔內存空間 
*/
Status DestoryStack_Sq(SqStack &S){

    //棧底指針保存的是順序棧內存空間的首地址 
    free(S.base);

    //操作成功 
    printf("順序棧內存釋放成功!\n"); 
    return OK; 
}//DestoryStack_Sq

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>3.置空順序棧<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

/*
    函數:ClearStack_Sq
    參數:SqStack &S 順序棧引用  
    返回值:狀態碼,OK表示操作成功 
    作用:將順序棧S中的元素清空
*/
Status ClearStack_Sq(SqStack &S){

    //只需要重新設置棧頂指針到初始位置,保留現有空間
    //棧頂指針和棧底指針都指向棧底表示此棧是空棧 
    S.top = S.base;

    //操作成功 
    return OK; 
}//ClearStack_Sq

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>4.判斷順序棧是否爲空<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

/*
    函數:StackIsEmpty_Sq
    參數:SqStack S 順序棧S 
    返回值:若順序棧S是空棧返回1,否返回0 
    作用:判斷順序棧S是否爲空棧
*/
Status StackIsEmpty_Sq(SqStack S){

    //棧頂指針和棧底指針都指向棧底表示此棧是空棧 
    return S.top == S.base; 
}//StackIsEmpty_Sq

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>5.獲取順序棧的長度<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

/*
    函數:StackLength_Sq
    參數:SqStack S 順序棧S 
    返回值:若順序棧S是空棧返回1,否返回0 
    作用:判斷順序棧S是否爲空棧
*/
Status StackLength_Sq(SqStack S){

    //棧的長度就是棧頂指針和棧底指針之間的元素個數 
    return (S.top - S.base); 
}//StackLength_Sq

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>6.獲得棧頂元素的值<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

/*
    函數:GetTop
    參數:SqStack S 順序棧S
    返回值:成功獲取順序棧S棧頂元素的值後返回OK,否則返回ERRROR
    作用:用e返回棧頂元素的值,但是棧頂元素不做出棧操作 
*/
Status GetTop(SqStack S, SElemType &e){

    //空棧沒有棧頂元素,所以要先判斷棧是否爲空 
    //注意棧是否爲空和棧是否存在不是一個概念,所以不可以用 
    //S.base != NULL判斷棧是否爲空 
    if(StackIsEmpty_Sq(S)) { 
         return ERROR;
    }//if

    //注意:棧頂指針指向棧頂元素的下一個位置
    e = *(S.top - 1);  
    /*   注意:此處不能使用“e = *(--S.top); ”的原因 
         1. --S.top自減操作改變了棧頂指針本身的指向,使得該指針向前移動一位,相當於刪除了原來棧中的最後一個元素(最後一個元素出棧); 
         2. S.top-1 僅僅表示棧頂指針的上一個位置,並沒有改變S.top的值,*(S.top-1)表示取棧頂指針前一個位置的值,即棧頂元素的值  
         3. 這兩種寫法造成的結果是不同的,如果是純代數運算,兩者沒有差別,但在指向數組
            (順序結構在C語言中是用一維數組描述的)的指針變量運算中,這兩個表達式有特殊含義 
            在指針運算中,“指針變量-1 ”表示該指針變量所指位置的前一個位置,
            這種做法並不改變指針變量本身的值。 
            --指針變量   不僅使得該指針指向原來所指位置的上一個位置, 還修改了指針變量本身的值
            在棧中,棧頂指針和棧底指針所指向的位置有特殊的含義,故兩者不等價。       
     */ 

     //操作成功 
     return OK; 
}//GetTop_Sq

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>7.在順序棧中插入元素(入棧)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

/*
    函數:ReallocStack_Sq
    參數:SqStack &S 順序棧S引用 
    返回值:狀態碼,操作成功返回OK,否則返回ERRROR
    作用:將棧S擴容,每擴容一次,棧的大小增加STACKINCREMENT
*/
Status ReallocStack_Sq(SqStack &S){

    //爲順序棧重新分配內存(擴容),擴展的空間大小是STACKINCREMENT
    /*if(!(S.base = (SElemType *)realloc(S.base, 
                (STACK_INIT_SIZE + STACKINCREMENT) * sizeof(SElemType))))
      這句代碼相當於:
      S.base = (SElemType *)realloc(S.base, 
                        (STACK_INIT_SIZE + STACKINCREMENT) * sizeof(SElemType));
      if(!S.base) <=> if(S.base == NULL)
    */
    if(!(S.base = (SElemType *)realloc(S.base, 
               (STACK_INIT_SIZE + STACKINCREMENT) * sizeof(SElemType)))){
        printf("內存分配失敗,程序即將退出!\n");
        exit(OVERFLOW);
    }//if

    //由於擴容前棧已經滿了,所以棧頂指針位置就是棧底指針+原來棧的大小 
    S.top = S.base + S.stacksize;

    //擴容後,棧的大小增加了STACKINCREMENT 
    S.stacksize += STACKINCREMENT;

    //操作成功 
    printf("順序棧S所需內存已重新分配成功!\n");
    return OK; 
}//ReallocStack_Sq

/*
    函數:Push_Sq
    參數:SqStack &S 順序棧引用
          SElemType e 被插入的元素e 
    返回值:成功獲取順序棧S棧頂元素的值後返回OK,否則返回ERRROR
    作用:(入棧、壓棧)插入元素e爲新的棧頂元素
*/
Status Push_Sq(SqStack &S, SElemType e){ 

    //入棧時發現棧滿了,就要追加存儲空間(擴容) 
    if(S.top - S.base >= S.stacksize) {  

        //調用擴容函數
        ReallocStack_Sq(S);
    }//if

    //插入前,棧頂指針指向當前棧頂元素的下一個位置 
    //將e賦值給棧頂指針所指存儲空間(插入元素e),棧頂指針後移
    //*S.top++ = e;  <=>  *(S.top) = e;  S.top++; 
    *S.top++ = e;

}//Push_Sq

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>8.在順序棧中刪除元素(出棧)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

/*
    函數:Pop_Sq
    參數:SqStack &S 順序棧引用
          SElemType &e 帶回被刪除的元素值e 
    返回值:刪除成功返回OK,否則返回ERRROR
    作用:(出棧,彈棧)若棧不空,則刪除S的棧頂元素,用e返回其值
*/
Status Pop_Sq(SqStack &S, SElemType &e){ 

    //在空棧中執行出棧操作沒有意義,所以要判斷棧是否爲空
    //注意棧是否爲空和棧是否存在不是一個概念,所以不可以用 
    //S.base != NULL判斷棧是否爲空 
    if(StackIsEmpty_Sq(S)) { 
         return ERROR;
    }//if

    //刪除前,棧頂指針指向當前棧頂元素的下一個位置
    //--S.top;之後,棧頂指針剛好指向被刪除元素 
    //棧頂指針前移,保存被刪除的元素值到e
    //e=*--S.top;  <=>  --S.top;   e=*(S.top);
    e = *--S.top;

    //操作成功 
    return OK; 
}//Pop_Sq

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>9.遍歷整個順序棧<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

/*
    函數:Print
    參數:ElemType e 被訪問的元素 
    返回值:狀態碼,操作成功返回OK,操作失敗返回ERROR 
    作用:訪問元素e的函數,通過修改該函數可以修改元素訪問方式,
          該函數使用時需要配合遍歷函數一起使用。 
*/
Status Print(SElemType e){
    printf("%5d  ", e);
    return OK;
}//Print 

/*
    函數:StackTraverse_Sq
    參數:SqStack S 順序棧S 
          Status(* visit)(SElemType) 函數指針,指向元素訪問函數。 
    返回值:狀態碼,操作成功返回OK,操作失敗返回ERROR 
    作用:調用元素訪問函數按出棧順序完成順序棧的遍歷,但並未真正執行出棧操作 
*/
Status StackTraverse_Sq(SqStack S, Status(* visit)(SElemType)) {

    //在空棧中執行遍歷操作沒有意義,所以要判斷棧是否爲空
    //注意棧是否爲空和棧是否存在不是一個概念,所以不可以用 
    //S.base != NULL判斷棧是否爲空 
    if(StackIsEmpty_Sq(S)) {
        printf("此棧是空棧"); 
        return ERROR;
    }//if

    //調用元素訪問函數依次訪問棧中的每個元素
    for(int i = 0; i < StackLength_Sq(S); ++i){

        //調用元素訪問函數,一旦訪問失敗則退出  
        if(!visit(S.base[i])) {
            return ERROR;
        }//if 
    }//for

    //輸出換行,是控制檯顯示美觀 
    printf("\n");

    //操作成功 
    return OK;
}//StackTraverse_Sq

//-------------------------------------------主函數--------------------------------------------------- 
int main(int argc,char *argv[]){
    SqStack S;
    SElemType e;
    int tmp,tmp1=0,i,n;
    while(1){
        printf("\n*****************************順序棧完整版測試程序******************************\n");
        printf("->1.初始化順序棧S\n");
        printf("->2.清空順序棧S\n");
        printf("->3.輸出順序棧S的所有元素\n");
        printf("->4.查看棧的長度(元素個數)\n");
        printf("->5.獲得棧頂元素的值\n");
        printf("->6.在順序棧中插入元素(入棧)\n");
        printf("->7.在順序棧中刪除元素(出棧)\n");
        printf("->8.進位制轉換程序\n");
        printf("->9.銷燬順序棧S\n");
        printf("->10.退出程序\n"); 
        while(1){
            printf("請輸入您想要操作的代號:");
            scanf("%d",&tmp);
            switch(tmp){
                case 1:{
                     if(tmp1){//若棧已經被初始化並且棧中含有元素
                        printf("順序棧已經被創建,正在銷燬...\n");
                        DestoryStack_Sq(S);
                     }//if
                     InitStack_Sq(S);
                     printf("您想爲順序棧S輸入幾個元素?\n"); 
                     scanf("%d",&n);
                     printf("請輸入順序棧S的所有元素,每個元素用空格隔開:\n");
                     for(i=0;i<n;i++){
                        scanf("%d",&e);
                        Push_Sq(S,e);
                     }//for
                     printf("創建後的順序棧S的結果爲:\n");
                     StackTraverse_Sq(S, Print);
                     printf("順序棧S創建成功!\n");
                     tmp1=1;
                     break;
                }//case 1
                case 2:{
                     if(!tmp1){
                        printf("順序棧S不存在,您可能還未創建,請在創建(執行操作1)後執行該操作!\n\n");
                        break;
                     }//if   
                     ClearStack_Sq(S);
                     printf("棧已清空,長度爲%d\n",StackLength_Sq(S));
                     break;
                }//case 2
                case 3:{
                     if(!tmp1){
                        printf("順序棧S不存在,您可能還未創建,請在創建(執行操作1)後執行該操作!\n\n");
                        break;
                     }//if
                     if(!StackLength_Sq(S)){
                        printf("棧可能已被清空或刪光,沒有元素可供輸出,請初始化後執行操作!\n");
                        break;
                     }//if
                     printf("順序棧S內的全部元素爲:\n");
                     StackTraverse_Sq(S, Print);
                     break;
                }//case 3
                case 4:{
                     if(!tmp1){
                        printf("順序棧S不存在,您可能還未創建,請在創建(執行操作1)後執行該操作!\n\n");
                        break;
                     }//if
                     printf("順序棧S的長度爲%d\n",StackLength_Sq(S));
                     break;
                }//case 4
                case 5:{             
                     if(!tmp1){
                        printf("順序棧S不存在,您可能還未創建,請在創建(執行操作1)後執行該操作!\n\n");
                        break;
                     }//if
                     if(!StackLength_Sq(S)){
                        printf("棧可能已被清空或刪光,沒有元素可供輸出,請初始化後執行操作!\n");
                        break;
                     }//if
                     if(GetTop(S,e))
                        printf("棧頂元素的值爲%5d\n",e);  
                     break;
               }//case 5
               case 6:{
                     if(!tmp1){
                        printf("順序棧S不存在,您可能還未創建,請在創建(執行操作1)後執行該操作!\n\n");
                        break;
                     }//if
                     printf("您想爲順序棧S插入幾個元素?\n"); 
                     scanf("%d",&n);
                     printf("插入前棧S內的全部元素爲:\n");
                     StackTraverse_Sq(S, Print);
                     printf("請依次輸入您想插入的所有元素,每個元素用空格隔開:\n");
                     for(i=0;i<n;i++){
                        scanf("%d",&e);
                        Push_Sq(S,e);
                     }//for
                     printf("插入後棧S內的全部元素爲:\n");
                     StackTraverse_Sq(S, Print);
                     break;
               }//case 6
               case 7:{
                     if(!tmp1){
                        printf("順序棧S不存在,您可能還未創建,請在創建(執行操作1)後執行該操作!\n\n");
                        break;
                     }//if
                     if(!StackLength_Sq(S)){
                        printf("棧可能已被清空或刪光,沒有元素可供輸出,請初始化後執行操作!\n");
                        break;
                     }//if
                     printf("您想在棧中刪除幾個元素?\n"); 
                     scanf("%d",&n);
                     printf("刪除前棧S內的全部元素爲:\n");
                     StackTraverse_Sq(S, Print);
                     for(i=0;i<n;i++){
                        Pop_Sq(S,e); 
                     }//for
                        printf("刪除後棧S內的全部元素爲:\n");
                        StackTraverse_Sq(S, Print);                 
                     break;
               }//case 7
               case 8:{
                     if(!tmp1){
                        free(S.base);
                        break;
                     }//if
                     int i;
                     InitStack_Sq(S);
                     printf("請輸入一個十進制整數:\n");
                     scanf("%d",&n);
                     printf("您想把它轉化成幾進制,請輸入一個不超過16的正整數:\n");
                     scanf("%d",&i);
                     if(i<=0||i>16){
                        printf("您輸入的數字不合法\n");
                        break;
                     }//if
                     while(n){
                        Push_Sq(S,n%i);
                        n=n/i;
                     }//while
                     printf("您想要的%d進制數爲:",i);
                     while(!StackIsEmpty_Sq(S)){
                        Pop_Sq(S,e);
                        switch(e){
                            case 1:       case 2:       case 3:      case 4:       case 5:
                            case 6:       case 7:       case 8:      case 9:
                            {           printf("%d",e);   break;  }
                            case 10:{   printf("A");      break;  }
                            case 11:{   printf("B");      break;  }
                            case 12:{   printf("C");      break;  }
                            case 13:{   printf("D");      break;  }
                            case 14:{   printf("E");      break;  }
                            case 15:{   printf("F");      break;  } 
                            default :{  printf("程序出現錯誤!\n"); break;   }
                        }//switch
                     }//while
                     printf("\n");
                     DestoryStack_Sq(S);
                     break;
               }//case 8
               case 9:{
                     if(!tmp1){
                        printf("順序棧S不存在,您可能還未創建,請在創建(執行操作1)後執行該操作!\n\n");
                        break;
                     }//if
                     printf("->銷燬順序棧S:"); 
                     DestoryStack_Sq(S);
                     tmp1=0;
                     break;
               }//case 9
               case 10:{
                     printf("程序退出,再見!\n\n");
                     exit(0);
                     break;
               }//case 10
               default:{
                     printf("您的輸入非法,請重新輸入!\n\n");
                     break; 
               }//default
            }//switch
            break;  
        }//while  
        system("pause"); 
        system("cls");  //清屏 
        fflush(stdin);  //清空標準輸入緩衝區,避免多輸入字符(如回車、空格)造成影響 
    }//while        
    return 0;
}

以下是程序運行時的部分輸出和我輸入的測試數據:

注:程序中涉及到菜單刷新,這裏不再重複截取菜單,只保留輸入數據和程序的結果輸出 

*****************************順序棧完整版測試程序******************************
->1.初始化順序棧S
->2.清空順序棧S
->3.輸出順序棧S的所有元素
->4.查看棧的長度(元素個數)
->5.獲得棧頂元素的值
->6.在順序棧中插入元素(入棧)
->7.在順序棧中刪除元素(出棧)
->8.進位制轉換程序
->9.銷燬順序棧S
->10.退出程序
請輸入您想要操作的代號:1
順序棧S所需內存已分配成功!
您想爲順序棧S輸入幾個元素?
5
請輸入順序棧S的所有元素,每個元素用空格隔開:
1 4 5 9 2
創建後的順序棧S的結果爲:
    1      4      5      9      2
順序棧S創建成功!
請按任意鍵繼續. . .

請輸入您想要操作的代號:3
順序棧S內的全部元素爲:
    1      4      5      9      2
請按任意鍵繼續. . .

請輸入您想要操作的代號:4
順序棧S的長度爲5
請按任意鍵繼續. . .

請輸入您想要操作的代號:5
棧頂元素的值爲    2
請按任意鍵繼續. . .

請輸入您想要操作的代號:6
您想爲順序棧S插入幾個元素?
2
插入前棧S內的全部元素爲:
    1      4      5      9      2
請依次輸入您想插入的所有元素,每個元素用空格隔開:
45 67
插入後棧S內的全部元素爲:
    1      4      5      9      2     45     67
請按任意鍵繼續. . .

請輸入您想要操作的代號:7
您想在棧中刪除幾個元素?
3
刪除前棧S內的全部元素爲:
    1      4      5      9      2     45     67
刪除後棧S內的全部元素爲:
    1      4      5      9
請按任意鍵繼續. . .

請輸入您想要操作的代號:8
順序棧S所需內存已分配成功!
請輸入一個十進制整數:
45
您想把它轉化成幾進制,請輸入一個不超過16的正整數:
16
您想要的16進制數爲:2D
順序棧內存釋放成功!
請按任意鍵繼續. . .

請輸入您想要操作的代號:2
棧已清空,長度爲0
請按任意鍵繼續. . .
請輸入您想要操作的代號:3
棧可能已被清空或刪光,沒有元素可供輸出,請初始化後執行操作!
請按任意鍵繼續. . .

請輸入您想要操作的代號:9
->銷燬順序棧S:順序棧內存釋放成功!
請按任意鍵繼續. . .

請輸入您想要操作的代號:10
程序退出,再見!


--------------------------------
Process exited with return value 0
Press any key to continue . . .

總結:
本次的程序涉及到很多的編程技巧,尤其是對指針變量做++和–操作要格外小心,因爲它們與普通的變量做++和–操作的含義和後果都不一樣,稍有不慎就會惹出麻煩。

下次的文章會介紹另一種特殊的線性表——隊列的鏈式存儲實現。請大家繼續關注我的博客,期待下次再見!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章