1. 程式人生 > >棧和佇列(C語言版)

棧和佇列(C語言版)

間隔了好久,開始繼續複習。
棧和佇列是在程式中最常被用到的資料結構,其重要性不言而喻。

棧:

定義:限定僅在表尾進行插入和刪除操作的線性表,因此表尾稱之為棧頂,表頭為棧底,重要特點是後進先出(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;
}