棧和佇列(C語言版)
阿新 • • 發佈:2019-02-19
間隔了好久,開始繼續複習。
棧和佇列是在程式中最常被用到的資料結構,其重要性不言而喻。
棧:
定義:限定僅在表尾進行插入和刪除操作的線性表,因此表尾稱之為棧頂,表頭為棧底,重要特點是後進先出(LIFO)
操作:
- InitStack(&S) 初始化一個棧
- DestoryStack(&S)銷燬一個已經存在的棧
- ClearStack(&S)清空一個棧
- StackEmpty(S)判斷已存在的棧是否為空
- StackLength(S)求棧長度
- GetTop(S,&e)獲取棧頂部元素
- Push(&S,e)將一個元素e壓入棧(核心)
- Pop(&S,&e) 將棧頂元素出棧,並用e返回其值(核心)
實現(C語言):
和線性表的實現類似,棧也有兩種實現方式,分別為順序棧和鏈棧
順序棧的實現:
/*棧和佇列的實現(C語言版)-------順序棧*/
#include<stdio.h>
#include<malloc.h>
#include"string.h"
#define STACK_INIT_SIZE 100//棧的基礎容量
#define STACK_INCREMENT 100//棧增長量
#define overflow_error 0
#define OK 1
#define operate_error 2
#define stack_null_error 3
typedef struct{
int *top;
int *base;
int stackSize;
}SqStack;
/*
初始化順序棧
*/
int InitStack(SqStack *S){
(*S).base = (int *)malloc(STACK_INIT_SIZE * sizeof(int));
if( (!(*S).base) ){
exit(overflow_error);
}
(*S).top = (*S).base;
(*S).stackSize = STACK_INIT_SIZE;
return OK;
}
/*
入棧操作,elem為要入棧的元素
*/
int PushStack(SqStack *S,int elem){
//如果記憶體不夠用,則重新申請空間
if((*S).top-(*S).base>(*S).stackSize){
(*S).base = (int *)realloc((*S).base,((*S).stackSize+STACK_INCREMENT)*sizeof(int));
//未申請上空間
if(!(*S).base){
exit(overflow_error);
}
(*S).top = (*S).base+(*S).stackSize;
(*S).stackSize += STACK_INCREMENT;
}
*((*S).top)++ = elem;
return OK;
}
/*出棧操作,將棧頂元素出棧,並用elem將該元素返回*/
int PopStack(SqStack *S,int *elem){
//判斷是否棧空
if((*S).top == (*S).base){
return stack_null_error;
}
*elem = *--((*S).top);//將元素彈出棧,並將指標下移
return OK;
}
/*獲取棧頂元素,但是並不是將元素出棧,並用elem返回元素值*/
int GetTop(SqStack S,int *elem){
if(S.top == S.base){
return stack_null_error;
}
*elem = *(S.top-1);
return OK;
}
/*判斷是否棧空*/
int StackEmpty(SqStack s){
int flag = 0;
if(s.base == s.top){
flag = 0;
}else{
flag = 1;
}
return flag;
}
/*根據操作返回的結果進行成功與否的顯示*/
void Utils_Print_Msg(int flag){
if(flag == OK){
printf("成功\n");
}else{
printf("不成功\n");
}
}
/*主函式*/
int main(){
SqStack stack;
//棧初始化
int flag = InitStack(&stack);
Utils_Print_Msg(flag);
//入棧
flag = operate_error;
flag = PushStack(&stack,60);
flag = PushStack(&stack,50);
flag = PushStack(&stack,40);
flag = PushStack(&stack,30);
flag = PushStack(&stack,20);
Utils_Print_Msg(flag);
int getElem = 0;
GetTop(stack,&getElem);
printf("獲取到的棧頂元素是%d\n",getElem);
//出棧
int elem = 0;
flag = operate_error;
flag = PopStack(&stack,&elem);
if(flag == OK){
printf("%d出棧成功\n",elem);
}else{
printf("%d出棧失敗\n",elem);
}
//獲取棧頂元素
GetTop(stack,&getElem);
printf("獲取到的棧頂元素是%d\n",getElem);
return 0;
}
應用:
棧的應用十分廣泛,所以也產生了許多使用棧的經典應用演算法,幾個簡單的用用的簡單實現。
數制轉換:
/*
進位制轉換---除K取餘法
int Num_10 十進位制下的數
int Num_convered 要轉換的的進位制
*/
int Conversion(int Num_10,int Num_convered){
SqStack s;
InitStack(&s);
printf("數制轉換前%d\n",Num_10);
while(Num_10){
PushStack( &s,(Num_10%Num_convered) );
Num_10 = Num_10/Num_convered;
}
printf("轉換數制後");
while(StackEmpty(s)){
int e;
PopStack(&s,&e);
printf("%d",e);
}
printf("\n");
}
--------------------------------------
//在主函式中新增程式碼測試一下:
int num_10,num_convered;
printf("輸入十進位制數");
scanf("%d",&num_10);
printf("輸入要轉換的進位制");
scanf("%d",&num_convered);
Conversion(num_10,num_convered);
佇列:
定義:
佇列是一種先進先出的資料結構,只允許在表的一端進行插入,在表的另一端進行刪除元素。允許插入的一端叫隊尾,允許刪除的一端叫隊頭。
操作:
- InitQueue(&Q)初始化佇列
- DestoryQueue(&Q)銷燬佇列
- ClearQueue(&Q)清空佇列
- QueueEmpty(Q)佇列為空
- GetHead(Q,&e)獲得隊首元素,並用e返回其值,但是並不出隊
- EnterQueue(&Q,e)將元素e入隊
- DeleteQueue(&Q,&e)將元素出隊,並用e返回其值
實現(C語言版):
和之前的資料結構類似,佇列也有兩種實現方式,為順序佇列和鏈佇列
單鏈佇列的實現(C語言版):
/*棧和佇列的實現(C語言版)-------單鏈佇列*/
#include<stdio.h>
#include<malloc.h>
#define overflow_error 0
#define OK 1
#define operate_error 2
#define queue_null_error 3
/*佇列的資料節點*/
typedef struct QNode{
int data;
struct QNode *next;
}QNode,*QueuePtr;
/*對頭隊尾指標*/
typedef struct {
QueuePtr front;
QueuePtr rear;
}LinkQueue;
/*初始化一個單鏈表佇列*/
int InitQueue(LinkQueue *Q){
(*Q).front = (*Q).rear = (QueuePtr)malloc(sizeof(QNode));
if(!(*Q).front){
exit(overflow_error);
}
(*Q).front->next = NULL;
return OK;
}
/*將元素elem入隊*/
int EnterQueue(LinkQueue *Q,int elem){
QueuePtr newNode = (QueuePtr)malloc(sizeof(QNode));
if(!newNode){
exit(overflow_error);
}
newNode->data = elem;
newNode->next = NULL;
(*Q).rear->next = newNode;
(*Q).rear = newNode;
return OK;
}
/*將隊尾的元素出隊,並用elem將其值返回*/
int DeleteQueue(LinkQueue *Q,int *elem){
if((*Q).front == (*Q).rear){
return queue_null_error;
}
QueuePtr deleteNode = (*Q).front->next;
*elem = deleteNode->data;
(*Q).front->next = deleteNode->next;
if((*Q).rear == deleteNode){
(*Q).rear = (*Q).front;
}
free(deleteNode);
return OK;
}
/*根據操作返回的結果進行成功與否的顯示*/
void Utils_Print_Msg(int flag){
if(flag == OK){
printf("成功\n");
}else{
printf("不成功\n");
}
}
/*主函式*/
int main(){
LinkQueue queue;
//初始化佇列
int flag = operate_error;
flag = InitQueue(&queue);
Utils_Print_Msg(flag);
//將元素elem插入隊尾
flag = operate_error;
flag = EnterQueue(&queue,78);
flag = EnterQueue(&queue,567);
flag = EnterQueue(&queue,21);
flag = EnterQueue(&queue,26);
flag = EnterQueue(&queue,54);
flag = EnterQueue(&queue,34);
flag = EnterQueue(&queue,8);
flag = EnterQueue(&queue,37);
Utils_Print_Msg(flag);
//將隊頭元素出隊,並用elem將其值返回
flag = operate_error;
int deleteNum;
flag = DeleteQueue(&queue,&deleteNum);
if(flag){
printf("%d\n",deleteNum);
}else{
printf("失敗");
}
flag = DeleteQueue(&queue,&deleteNum);
if(flag){
printf("%d\n",deleteNum);
}else{
printf("失敗");
}
flag = DeleteQueue(&queue,&deleteNum);
if(flag){
printf("%d\n",deleteNum);
}else{
printf("失敗");
}
flag = DeleteQueue(&queue,&deleteNum);
if(flag){
printf("%d\n",deleteNum);
}else{
printf("失敗");
}
flag = DeleteQueue(&queue,&deleteNum);
if(flag){
printf("%d\n",deleteNum);
}else{
printf("失敗");
}
return 0;
}