C實現棧和隊列


  這兩天再學習了數據結構的棧和隊列,思想很簡單,可能是學習PHP那會沒有直接使用棧和隊列,寫的太少,所以用具體代碼實現的時候出現了各種錯誤,感覺還是C語言功底不行。棧和隊列不論在面試中還是筆試中都很重要,下面就介紹一下這兩天棧和隊列的學習經驗

一:棧的學習

基礎東西:棧是在表尾進行插入和刪除的線性表,由此可知表尾是棧頂,表頭為棧底,沒有任何元素的棧是空棧。根據棧的結構可以知道:棧修改是按后進先出的原則進行的(LIFO),基本操作有插入、刪除、初始化、取棧頂元素,判斷是否是空棧等等。

棧的表示和實現:和上一節介紹過的線性表相似棧有兩種表示方法(順序表示和鏈式表示)因為和線性表類似(特殊的線性表)我只介紹順序棧的就可以了。

順序棧:利用一組連續的地址來依次存儲棧的各個元素(從棧底到棧頂),用top指針指示棧頂元素,base指針指示棧底元素,所以top=base可以作為空棧的判斷。插入一個元素top++,出棧一個元素top--,所以非空棧的指針始終在棧頂元素的下一個位置

順序棧的結構體表示:

1 //棧的順序存儲表示
2 typedef struct{
3     SElemType *base;//在棧構造之前和銷毀后值是NULL
4     SElemType *top;
5     int stacksize; //已分配的存儲空間
6 }SqStack;

  下面是我練習的代碼,實現了棧的定義、棧的初始化、進棧操作、出棧操作、得到棧頂元素、遍歷棧。需要注意的是出棧操作和得到棧頂元素的操作是有區別的,希望對大家棧的學習和回顧有所幫助。代碼都是自己練習過的,可以直接運行

  1 /**
  2  * 棧
  3  * @author:zhaoyafei
  4  * @time:2015-6-16
  5  */
  6 #include <stdio.h>
  7 #include <stdlib.h>
  8 
  9 //預定義常量
 10 #define OK 1
 11 #define OVERFLOW -2
 12 #define ERROR 0
 13 
 14 #define STACK_INIT_SIZE 100 //存儲空間的初始分配量
 15 #define STACKINCREMENT 10   //存儲空間的分配增量stackincrement
 16 
 17 typedef int SElemType;
 18 
 19 //棧的順序存儲表示
 20 typedef struct{
 21     SElemType *base;//在棧構造之前和銷毀后值是NULL
 22     SElemType *top;
 23     int stacksize; //已分配的存儲空間
 24 }SqStack;
 25 
 26 //棧的初始化操作
 27 
 28 int InitStack(SqStack &S){
 29     S.base = (int *)malloc(STACK_INIT_SIZE * sizeof(SqStack));
 30     if(!S.base){
 31         exit(OVERFLOW);//分配空間失敗
 32     }
 33     S.top = S.base;
 34     S.stacksize = STACK_INIT_SIZE;
 35     return OK;
 36 }
 37 
 38 //進棧操作
 39 int Push(SqStack &S, int e){
 40     if(S.top - S.base >= S.stacksize){//棧空間已經滿
 41         S.base = (int *)realloc(S.base,(S.stacksize + STACKINCREMENT) * sizeof(SqStack));
 42         if(!S.base){
 43             exit(OVERFLOW);//分配失敗
 44         }
 45         S.top = S.base + S.stacksize;
 46         S.stacksize += STACKINCREMENT;
 47     }
 48     *S.top++ = e;
 49     return OK;
 50 }
 51 
 52 //出棧
 53 int Pop(SqStack &S,int &e){
 54     if(S.top != S.base){
 55         e = * --S.top;
 56         return OK;
 57     }else{
 58         exit(OVERFLOW);
 59     }
 60 }
 61 
 62 //得到頂部元素
 63 void GetElem(SqStack S, int &e){
 64     if(S.top != S.base){
 65         e = * (S.top - 1);
 66     }else{
 67         exit(OVERFLOW);
 68     }
 69 }
 70 
 71 //打印出棧各個元素
 72 void PrintfStack(SqStack S){
 73     while(*(S.top-1) && S.top != S.base){//證明不是空棧,且有值
 74         S.top = S.top - 1;
 75         printf("%d ",*S.top);
 76     }
 77     printf("\n");
 78 }
 79 
 80 int main(){
 81     int e,i;
 82     int TextData[6] = {9,2,8,1,7,6};
 83     SqStack Sa,Sb;
 84     InitStack(Sa);//初始化棧Sa;
 85     for(i = 0; i < 6; i++){
 86         Push(Sa,TextData[i]);
 87     }
 88     printf("**************棧基本操作*************\n");
 89     //初始化數據
 90     printf("初始化后的Sa:");
 91     PrintfStack(Sa);
 92     
 93     //得到棧頂元素
 94     GetElem(Sa,e);
 95     printf("Sa棧頂元素是:%d\n",e);
 96 
 97     //初始化數據
 98     printf("頂部出棧后Sa:");
 99     Pop(Sa,e);
100     PrintfStack(Sa);    
101 }

二:隊列的學習:

隊列和棧相反,是一種先進先出(FIFO)的線性表,只能在一端進行插入,一端進行刪除

基礎:在隊列中,進行出入的一端稱作隊尾,允許刪除的一端稱作隊首。和線性表差不多可以用順序和鏈式表示。

雙端隊列:雙端隊列是限定插入和刪除的操作在表的兩端進行的線性表,用的不是很多。

循環隊列:百度上解釋:”將向量空間想象為一個首尾相接的圓環,並稱這種向量為循環向量“,其實就是把隊列首尾相連,但是要有一定的要求,不是想怎么連就怎么連。

下面給出鏈表的結構體:

 1 //單鏈隊列
 2 typedef struct QNode{
 3     QElemType data;
 4     struct QNode *next;
 5 }QNode, *QueuePtr;
 6 
 7 typedef struct{
 8     QueuePtr front;
 9     QueuePtr rear;
10 }LinkQueue;
11 
12 //循環隊列
13 typedef struct{
14     QElemType *base;
15     int front;
16     int rear;
17 }SqQueue;

  下面這段代碼練習了隊列的基本操作:隊列結構體定義(比棧的稍微復雜一點)、在隊尾插入新元素、刪除隊頭元素、銷毀隊列、打印隊列、循環隊列的定義等等,這部分牽涉到好多的指針操作,如果有些困難可以在紙上划出隊列的結構,列出指針的操作前后變化,就容易多了(個人感覺如果線性表學好了,這些操作根本不在話下)。需要注意循環隊列操作中取余操作:(Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;

廢話不多說,下面直接給出具體實現的代碼:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 //頭文件
  4 #define ERROR -1
  5 #define OK 2;
  6 #define TRUE 1;
  7 #define OVERFLOW -2;
  8 
  9 //最大隊列長度
 10 #define MAXQSIZE 100
 11 
 12 typedef int Status;
 13 typedef int QElemType;
 14 
 15 //單鏈隊列
 16 typedef struct QNode{
 17     QElemType data;
 18     struct QNode *next;
 19 }QNode, *QueuePtr;
 20 
 21 typedef struct{
 22     QueuePtr front;
 23     QueuePtr rear;
 24 }LinkQueue;
 25 
 26 //循環隊列
 27 typedef struct{
 28     QElemType *base;
 29     int front;
 30     int rear;
 31 }SqQueue;
 32 
 33 //********************************隊列的基本操作*****************************
 34 //初始化隊列
 35 Status InitQueue(LinkQueue &Q){
 36     Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode));//動態分配空間
 37     if(!Q.front){
 38         exit(ERROR);//分配空間失敗
 39     }
 40     Q.front->next = NULL;
 41     return OK;
 42 }
 43 
 44 //在隊尾插入新元素
 45 Status EnQueue(LinkQueue &Q, int e){
 46     QueuePtr p;
 47     p = (QueuePtr)malloc(sizeof(QNode));
 48     if(!p){
 49         exit(ERROR);//分配失敗
 50     }
 51     p->data = e;
 52     p->next = NULL;
 53     Q.rear->next = p;
 54     Q.rear = p;
 55     return OK;
 56 }
 57 
 58 void DestroyQueue(LinkQueue &Q){
 59     if(Q.front != Q.rear){
 60         while(Q.front){
 61             Q.rear = Q.front->next;
 62             free(Q.front);
 63             Q.front = Q.rear;
 64         }
 65     }
 66 }
 67 
 68 //刪除隊頭元素,並用e返回
 69 Status DeQueue(LinkQueue &Q, int &e){
 70     if(Q.front != Q.rear){//先判斷隊列是否為空
 71         QueuePtr p;
 72         e = Q.front->next->data;
 73         if(Q.front->next == Q.rear){//隊列只有一個元素
 74             p = Q.rear;
 75             Q.rear = Q.front;
 76             Q.front->next = NULL;
 77         }else{
 78             p = Q.front->next;
 79             Q.front->next = p->next;
 80             p->next = NULL;
 81         }    
 82         free(p);
 83         return OK;
 84     }
 85 }
 86 
 87 //打印隊列元素
 88 void PrintQueue(LinkQueue Q){
 89     if(Q.front != Q.rear){
 90         do{
 91             Q.front = Q.front->next;
 92             printf("%d ",Q.front->data);
 93         }while(Q.front->next);
 94     }
 95     printf("\n");
 96 }
 97 
 98 //********************************循環隊列的基本操作*****************************
 99 //初始化隊列
100 Status InitQueueXh(SqQueue &Q){
101     Q.base = (int *)malloc(MAXQSIZE * sizeof(int));//動態分配空間
102     if(!Q.base){
103         exit(ERROR);//分配空間失敗
104     }
105     Q.front = Q.rear = 0;
106     return OK;
107 }
108 
109 //在隊尾插入新元素
110 Status EnQueueXh(SqQueue &Q, int e){
111     if((Q.rear + 1) % MAXQSIZE == Q.front){
112         exit(ERROR);//隊循環列已滿
113     }
114     Q.base[Q.rear] = e;
115     Q.rear = (Q.rear + 1) % MAXQSIZE;
116     return OK;
117 }
118 
119 int DestroyQueueXh(SqQueue &Q){
120     return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
121 }
122 
123 //刪除隊頭元素,並用e返回
124 Status DeQueueXh(SqQueue &Q, int &e){
125     if(Q.front == Q.rear){//先判斷隊列是否為空
126         return false;
127     }
128     e = Q.base[Q.front];
129     Q.front = (Q.front + 1) % MAXQSIZE;
130     return OK;
131 }
132 
133 //打印隊列元素
134 void PrintQueueXh(SqQueue Q){
135     if(Q.front != Q.rear){
136         do{
137             printf("%d ",Q.base[Q.front]);
138             Q.front++;
139         }while(Q.front != Q.rear);
140     }
141     printf("\n");
142 }
143 
144 //主方法
145 int main(){
146     int e, i;
147     int Data[6] = {3,1,7,8,9,1};
148 
149     printf("****************隊列的基本操作**************\n");
150     //初始化隊列
151     LinkQueue Qa, Qb;
152     InitQueue(Qa);
153     //初始化Qa
154     for(i = 0; i < 6; i++){
155         EnQueue(Qa,Data[i]);
156     }    
157     //打印Qa
158     printf("Qa的各個元素:");
159     PrintQueue(Qa);
160 
161     //刪除隊首元素
162     DeQueue(Qa,e);
163     printf("刪除Qa的隊首元素:%d\n",e);
164     printf("刪除首元素后的Qa: ");
165     PrintQueue(Qa);
166     printf("銷毀后的Qa: ");
167     DestroyQueue(Qa);
168     PrintQueue(Qa);
169 
170     printf("**************循環隊列的基本操作************\n");
171     //初始化隊列
172     SqQueue QaXh, QbXh;
173     InitQueueXh(QaXh);
174     //初始化Qa
175     for(i = 0; i < 6; i++){
176         EnQueueXh(QaXh,Data[i]);
177     }    
178     //打印Qa
179     printf("QaXh的各個元素:");
180     PrintQueueXh(QaXh);
181 
182     //刪除隊首元素
183     DeQueueXh(QaXh,e);
184     printf("刪除QaXh的隊首元素:%d\n",e);
185     printf("刪除首元素后的QaXh: ");
186     PrintQueueXh(QaXh);
187     printf("得到QaXh的元素個數:%d\n",DestroyQueueXh(QaXh));
188 }


免責聲明!

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



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