順序棧的基本操作(C語言)


  由於現在只學了C語言所以就寫這個C語言版的棧的基本操作

這里說一下 :網上和書上都有這種寫法 int InitStack(SqStack &p)

&p是取地址  但是這種用法好像C並不支持 ,C++才支持,所以用

C語言寫就需要使用指針

代碼如下:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #define STACK_INIT_SIZE 100//儲存空間初始分配量
  4 #define STACKINCREMENT  10//存儲空間分配增量
  5 #define OK 1
  6 #define ERROR 0
  7 typedef int StackType; //棧元素類型
  8  
  9 typedef struct {
 10     StackType *base;   //在構造之前和銷毀之后,base的值為NULL
 11     StackType *top;    //棧頂指針
 12     int stacksize;     //當前已分配的存儲空間,以元素為單位
 13 }SqStack; //順序棧
 14 
 15 //棧的初始化
 16 int InitStack(SqStack *p) {
 17     
 18     
 19     p->base = (StackType*)malloc(STACK_INIT_SIZE * sizeof(StackType));
 20     if (p->base == NULL)  return ERROR;  //內存分配失敗
 21     p->top = p->base;     //棧頂與棧底相同表示一個空棧
 22     p->stacksize = STACK_INIT_SIZE;
 23     return OK;
 24 
 25 }
 26 //判斷棧是否為空
 27 int EmptyStack(SqStack *p) {
 28     //若為空棧 則返回OK,否則返回ERROR
 29     if (p->top == p->base) return OK;
 30     else return ERROR;
 31 }
 32 //順序棧的壓入
 33 int Push(SqStack *p,StackType e) {
 34     //插入元素e為新的棧頂元素
 35     if ((p->top - p->base)>= p->stacksize)   //棧滿,追加儲存空間
 36     {
 37         p->base = (StackType*)realloc(p->base, (p->stacksize + STACKINCREMENT) * sizeof(StackType));
 38         if (p->base == NULL)   return ERROR;// 儲存空間分配失敗
 39         p->top = p->base + p->stacksize;    //可能有人覺得這句有點多余(我當時也是這么想的 后面有解釋)
 40         p->stacksize += STACKINCREMENT;
 41     }
 42     *(p->top) = e;
 43     (p->top)++;
 44     return OK;
 45 }
 46  // 順序棧的彈出     
 47 int Pop(SqStack *p,StackType *e) {
 48     //若棧不空,則刪除p的棧頂元素,用e返回其值
 49     if (p->top == p->base) return ERROR;
 50     --(p->top);
 51     *e = *(p->top);
 52     return OK;
 53     
 54 
 55 }
 56 //順序棧的銷毀
 57 int DestroyStack(SqStack *p) {
 58     //釋放棧底空間並置空
 59         free(p->base);
 60         p->base = NULL;
 61         p->top = NULL;
 62         p->stacksize = 0;
 63         
 64         return OK;
 65 }
 66 //將順序棧置空 棧還是存在的,棧中的元素也存在,如果有棧中元素的地址任然能調用
 67 int ClearStack(SqStack *p) {
 68     p->top= p->base;
 69     return OK;
 70 }
 71 //返回順序棧的元素個數
 72 int StackLength(SqStack p) {
 73     //棧頂指針減去棧底指針等於長度,因為棧頂指針指向當前棧頂元素的下一個位置
 74     return p.top - p.base;
 75 }
 76 //返回順序棧的棧頂元素
 77 int GetTop(SqStack *p, StackType *e) {
 78     //若棧不為空,則用e返回p的棧頂元素
 79     if (p->top > p->base) {
 80         *e = *(p->top - 1); return OK;
 81     }
 82     else return ERROR;
 83 }
 84 //從棧頂到棧底對每個元素調用某個函數
 85 int StackTraverse(SqStack p,void (*pfun)(StackType)/*函數指針*/){
 86 //從棧底到棧頂依次對棧中的每個元素調用函數pfun()
 87     while (p.top > p.base)
 88     pfun(*(p.base)++);                //先調用后遞增
 89     printf("\n");
 90     return OK;
 91 }
 92 //打印棧中元素
 93 void print(StackType stack) {
 94     printf("%d\n", stack);
 95     
 96 }
 97 //測試棧的各種操作
 98 int main() {
 99     int n,i;
100     StackType *e,a;
101     SqStack *pstack,stack;
102     pstack = &stack;
103     e=(StackType*)malloc(sizeof(StackType));    //為指針e分配內存地址
104     InitStack(pstack);                            //初始化棧
105 
106     if (EmptyStack(pstack) == 1) printf("-------棧為空-------\n");
107     printf("請輸入棧的元素個數:");
108     scanf("%d", &n);
109     for (i = 0; i < n; i++)
110     {
111         scanf("%d", &a);
112         Push(pstack, a);
113     }
114     if (EmptyStack(pstack) == 0) printf("-------棧不為空-----\n");
115         
116     printf("棧的長度為:%d\n", StackLength(stack));
117     printf("--------------------\n");
118     printf("請輸入一個入棧元素:");
119     scanf("%d", &a);
120     Push(pstack, a);
121     printf("--------------------\n");
122     printf("棧中的元素個數為:%d\n", StackLength(stack));
123     printf("--------------------\n");
124     GetTop(pstack, e);
125     printf("棧頂元素為:%d\n", *e);
126     printf("--------------------\n");
127     printf("打印棧中的元素:\n");
128     StackTraverse(stack, print);
129     printf("---彈出棧頂元素---\n");
130     Pop(pstack, e);
131     printf("彈出的棧頂元素為:%d\n", *e);
132     printf("--------------------\n");
133     GetTop(pstack, e);
134     printf("棧頂元素為:%d\n", *e);
135     printf("--------------------\n");
136     printf("打印棧中的元素:\n");
137     StackTraverse(stack, print);
138     printf("--------------------\n");
139 
140     printf("----------清空棧-------\n");
141     if (ClearStack(pstack) == 0)  printf("已清空棧\n");
142     
143     printf("----------銷毀棧-------\n");
144     if (DestroyStack(pstack) == 0)  printf("已銷毀棧\n");
145     return 0;
146    
147 }
    

 

      第39行  p->top = p->base + p->stacksize;這句有必要加上嗎?  答案是肯定的。
        這一個問題的關鍵在於 realloc 是怎么實現的,有兩種情況:

   如果有足夠空間用於擴大mem_address指向的內存塊,則分配額外內存,並返回mem_address。
 這里說的是“擴大”,我們知道,realloc是從堆上分配內存的,當擴大一塊內存空間時,
realloc()試圖直接從堆上現存的數據后面的那些字節中獲得附加的字節,如果能夠滿足,自然天下太平。
 也就是說,如果原先的內存大小后面還有足夠的空閑空間用來分配,加上原來的空間大小= newsize。
那么就ok。得到的是一塊連續的內存。
   如果原先的內存大小后面沒有足夠的空閑空間用來分配,那么從堆中另外找一塊newsize大小的內存。
 並把原來大小內存空間中的內容復制到newsize中。返回新的mem_address指針。(數據被移動了)。老塊被放回堆上。
 如果是第二種情況的話,s->top 就不是原來的 top 了     --百度百科

  寫這些代碼的時候還是遇到了一些問題 在這里總結一下:

  第一 對於指針的使用要慎重 因為它傳遞進函數會改變原始數據,所以對於不需要改變

指針指向的值的情況就不要使用指針。

  第二 對於指針的使用  如下定義 int *e=NULL; *e=3;

看着好像沒有問題  編譯也沒問題 但是運行程序就出錯

為什么?  沒有為指針e分配內存地址 所以引用肯定錯誤啊(我這個逗逼錯誤-_-)

正確的用法應該是 int *e=NULL;e=(int*)malloc(sizeof(int)); *e=3;

我之前都是 int *e,a; e=&a; e=3; 這種用法 所以......

 

 
        

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM