中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C語言數據結構的棧和隊列詳解

發布時間:2021-09-17 20:23:42 來源:億速云 閱讀:144 作者:chen 欄目:開發技術

這篇文章主要介紹“C語言數據結構的棧和隊列詳解”,在日常操作中,相信很多人在C語言數據結構的棧和隊列詳解問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”C語言數據結構的棧和隊列詳解”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

目錄
    • 數組實現

    • 標題全部代碼

      • Stack_array.c

      • Stack_array.h

      • 初始化數組棧

      • 滿棧后擴容

      • 是否為空棧

      • 壓棧和退棧

  • 鏈表實現

    • stack_chain.h

      • stack_chain.c

        • 整個壓棧流程

          • 整個彈棧流程

            • 出棧情況

            • 隊列

              • 隊列的實現

                • queue_chain.h

                • queue_chain.c

              • 一個結構體類型用于維護這個隊列

                • 概念流程圖

                  • 入隊列的實現

                    • 出隊列的實現

                      • 是否空隊

                      棧是一種以后進先出為順序對對象進行添加或刪除的數據結構
                      對棧進行形象記憶就像是桌子上的一堆書或一堆盤。對盤子取或者存盤子,都只能對最上面的書或者盤子進行操作。

                      C語言數據結構的棧和隊列詳解

                      對于棧而言,只有彈棧才能獲取其數據。
                      當我們用C語言實現棧這個數據結構。
                      其實有三種方法實現

                      1,數組

                      2,單鏈表

                      3,雙向鏈表

                      但是,對于雙向鏈表,實現棧而言過于復雜。
                      可以選擇數組或者單鏈表。

                      數組實現

                      標題全部代碼

                      Stack_array.c
                      #include "Stack_array.h"
                      void InitStack(STstack* st)//棧的初始化
                      {
                      	st->top = 0;
                      	st->arr = (STData*)malloc(CAP*sizeof(STData));
                      	st->capacity = CAP;
                      }
                      void StackPush(STstack* st, STData n)//元素入棧
                      {
                      	if (st->top == st->capacity)//判斷是否需要擴容
                      	{
                      		StackExpansion(st);
                      	}
                      	st->arr[st->top++] = n;
                      }
                      STData StackPop(STstack* st)//元素退棧
                      {
                      	assert(st);
                      	assert(!StackEmpty(st));//判斷是否為空棧
                      	return st->arr[--st->top];
                      }
                      int StackEmpty(STstack* st)//判斷棧是否為空
                      {
                      	if (st->top == 0)
                      		return 1;
                      	return 0;
                      }
                      void StackDestory(STstack* st)//銷毀棧,防止內存泄漏
                      {
                      	free(st->arr);
                      	st->arr = NULL;
                      }
                      void StackExpansion(STstack* st)//擴容
                      {
                      	STData* tmp = (STData*)realloc((STData*)st->arr, sizeof(STData) * (st->capacity) * 2);
                      	if (tmp == NULL)
                      	{
                      		printf("Exparsion Error\n");
                      		exit(-1);
                      	}
                      	st->arr = tmp;
                      	st->capacity *= 2;
                      }
                      void StackPrint(STstack* st)//打印棧的元素,但前提是要退棧才能得到元素
                      {
                      	while(st->top)
                      	{
                      		STData ret = StackPop(st);
                      		printf("%d ", ret);
                      	}
                      }
                      Stack_array.h
                      #pragma once
                      #define _CRT_SECURE_NO_WARNINGS
                      #include <stdio.h>
                      #include <stdlib.h>
                      #include <assert.h>
                      #define CAP 4
                      typedef int STData;
                      typedef struct Stack//結構體用于維護棧
                      {
                      	int top;//棧頂標記
                      	STData* arr;//棧的指針
                      	int capacity;//棧的容量
                      }STstack;
                      void InitStack(STstack* st);//棧的初始化
                      void StackPush(STstack* st, STData n);//元素入棧
                      STData StackPop(STstack* st);//元素退棧
                      void StackExpansion(STstack* st);//擴容
                      int StackEmpty(STstack* st);//判斷棧是否為空
                      void StackDestory(STstack* st);//銷毀棧,防止內存泄漏
                      void StackPrint(STstack* st);//打印棧的元素,但前提是要退棧才能得到元素

                      對于數組實現而言。創建一個結構體用于維護整個棧。而其中有一個用于鏈接創建的數組。

                      typedef int STData;
                      typedef struct Stack//結構體用于維護棧
                      {
                      	int top;//棧頂標記
                      	STData* arr;//棧的指針
                      	int capacity;//棧的容量
                      }STstack;

                      作為數組棧,需要一個動態的數組。則這就需要一個Capacity作為衡量是否需要擴容的標準。而top需要作為入棧元素的位置。
                      當top的值等于Capacity時就意味著棧已經滿了。因為數組是從0開始的

                      C語言數據結構的棧和隊列詳解

                      初始化數組棧

                      在初始化時,要先動態開辟一個數組空間,且,未壓棧壓入數據元素,其top要設為0.要保證當需要壓棧時有明確指定的空間。同時,top的位置要為最后壓入數據的下一個下標。

                      void InitStack(STstack* st)//棧的初始化
                      {
                      	st->top = 0;
                      	st->arr = (STData*)malloc(CAP*sizeof(STData));
                      	st->capacity = CAP;
                      }
                      滿棧后擴容

                      其Capacity要作為判斷是否滿棧的標準。且,滿棧后要進行擴容(因為是動態數組)。

                      void StackExpansion(STstack* st)//擴容
                      {
                      	STData* tmp = (STData*)realloc((STData*)st->arr, sizeof(STData) * (st->capacity) * 2);
                      	if (tmp == NULL)
                      	{
                      		printf("Exparsion Error\n");
                      		exit(-1);
                      	}
                      	st->arr = tmp;
                      	st->capacity *= 2;
                      }

                      同時,還要每次更改棧的容量,為下一次是否滿棧作為標準。

                      是否為空棧
                      int StackEmpty(STstack* st)//判斷棧是否為空
                      {
                      	if (st->top == 0)
                      		return 1;
                      	return 0;
                      }

                      其是否為空。也就是top的位置在數組的0下標位。

                      壓棧和退棧
                      void StackPush(STstack* st, STData n)//元素入棧
                      {
                      	if (st->top == st->capacity)//判斷是否需要擴容
                      	{
                      		StackExpansion(st);
                      	}
                      	st->arr[st->top++] = n;
                      }
                      STData StackPop(STstack* st)//元素退棧
                      {
                      	assert(st);
                      	assert(!StackEmpty(st));//判斷是否為空棧
                      	return st->arr[--st->top];
                      }

                      壓棧
                      每次壓棧,都需要判斷是否滿棧,并決定是否擴容。
                      同時,當在原先top位置的數位置進行賦值。并之后要將top向后移動一個位置。保證下一次壓棧。

                      退棧
                      退棧返回top的上一個位置的元素。同時top向前移動一個位置,不需要free,下次壓棧會自動覆蓋。

                      鏈表實現

                      stack_chain.h

                      #include <stdio.h>
                      #include <stdlib.h>
                      #define N 3
                      typedef struct stackele
                      {
                      	int n;
                      	int* point;
                      }sta;
                      sta* top;
                      void initstack(sta* a);//初始化棧
                      void pushstack(sta* a,int num);//入棧
                      //void printstack(sta* a);//打印棧
                      //void fullstack(sta* a);//檢查是否滿棧的情況
                      void emptystack(sta* a);//檢查是否空棧的情況
                      int popstack(sta*a);//出棧

                      stack_chain.c

                      #include "stack_chain.h"
                      void initstack(sta* a)//初始化棧
                      {
                      	top= NULL;
                      }
                      void pushstack(sta* a, int num)//入棧
                      {
                      	sta* p = (sta*)malloc(sizeof(sta));
                      	p->n = num;//新節點賦值
                      	p->point = top;
                      	top = p;
                      }
                      int popstack(sta* a)//出棧
                      {
                      	emptystack(a);//檢查是否空棧的情況
                      	int date;
                      	sta* des = top;
                      	top = top->point;
                      	date = des->n;
                      	free(des);
                      	des = NULL;
                      	return date;
                      }
                      void emptystack(sta* a)//檢查是否空棧的情況
                      {
                      	if (top == NULL)
                      	{
                      		printf("Stack empty");
                      		exit(0);
                      	}
                      }

                      對于鏈表實現棧而言,和數組其實差不多。只不夠,每次壓棧都需要重新動態開辟一個新節點,并且鏈入棧中。但是,這并不是普通的直接鏈入。而是需要頭插入棧。

                      C語言數據結構的棧和隊列詳解

                      這樣頭插入棧,可以方便退棧的時候,可以找到上一個元素。而壓棧是不需要什么順序。每一個壓棧節點就是top節點。

                      整個壓棧流程

                      C語言數據結構的棧和隊列詳解

                      void pushstack(sta* a, int num)//入棧
                      {
                      	sta* p = (sta*)malloc(sizeof(sta));
                      	p->n = num;//新節點賦值
                      	p->point = top;
                      	top = p;
                      }

                      整個彈棧流程

                      C語言數據結構的棧和隊列詳解

                      int popstack(sta* a)//出棧
                      {
                      	emptystack(a);//檢查是否空棧的情況
                      	int date;
                      	sta* des = top;
                      	top = top->point;
                      	date = des->n;
                      	free(des);
                      	des = NULL;
                      	return date;
                      }

                      出棧情況

                      尤其要把握一個條件:空棧
                      由于不是數組,且鏈式結構的特性,是不需要擴容的。即不需要判斷滿棧的情況。
                      只考慮空棧的條件

                      void emptystack(sta* a)//檢查是否空棧的情況
                      {
                      	if (top == NULL)
                      	{
                      		printf("Stack empty");
                      		exit(0);
                      	}
                      }

                      這里空棧的條件是top指針指向NULL時也就是

                      C語言數據結構的棧和隊列詳解

                      為什么呢?
                      因為每次彈棧的時候,都會free掉top指向的空間然后讓top指向下一個節點。就這樣不斷移動。但是我設計初始化的時候是top= NULL;而且每次壓棧都是p->point = top;這就會有一個標準來限定空棧的情況。

                      對于棧而言,其更像是一個遞歸的具象化。

                      隊列

                      C語言數據結構的棧和隊列詳解

                      這種數據結構就像是銀行柜臺的取號機,
                      先取號的先去柜臺。

                      始終滿足先入先出的概念

                      隊列的實現

                      queue_chain.h
                      #define _CRT_SECURE_NO_WARNINGS
                      #include <stdio.h>
                      #include <stdlib.h>
                      #include <assert.h>
                      typedef int QUData;
                      typedef struct queue
                      {
                      	QUData data;
                      	struct queue* next;
                      }queue;
                      typedef struct Queue//結構體用于維護隊列
                      {
                      	queue* Dequeue;//隊頭指針
                      	queue* Enqueue;//隊尾指針
                      }QUqueue;
                      void InitQueue(QUqueue* qu);//棧的初始化
                      void QueuePush(QUqueue* qu, QUData n);//元素入隊
                      QUData QueuePop(QUqueue* qu);//元素出隊
                      int QueueEmpty(QUqueue* qu);//判斷隊列是否為空
                      void QueueDestory(QUqueue* qu);//銷毀隊,防止內存泄漏
                      void QueuePrint(QUqueue* qu);//打印隊列中的元素,但前提是要出隊才能得到元素
                      queue_chain.c
                      #include "queue_chain.h"
                      void InitQueue(QUqueue* qu)//隊列的初始化
                      {
                      	qu->Dequeue = qu->Enqueue = NULL;
                      }
                      void QueuePush(QUqueue* qu, QUData n)//元素入隊
                      {
                      	queue* newcell = (QUData*)malloc(sizeof(QUData));
                      	newcell->data = n;
                      	newcell->next = NULL;
                      	if (qu->Dequeue == NULL)
                      	{
                      		qu->Enqueue = qu->Dequeue = newcell;
                      	}
                      	else
                      	{
                      		qu->Enqueue->next = newcell;
                      		qu->Enqueue = newcell;
                      	}
                      }
                      QUData QueuePop(QUqueue* qu)//元素出隊
                      {
                      	if (QueueEmpty(qu))
                      	{
                      		printf("Queue Is Empty");
                      		exit(-1);
                      	}
                      	QUData ret = qu->Dequeue->data;
                      	qu->Dequeue = qu->Dequeue->next;
                      	return ret;
                      }
                      int QueueEmpty(QUqueue* qu)//判斷隊列是否為空
                      {
                      	if (qu->Dequeue == qu->Enqueue)
                      		return 1;
                      	return 0;
                      }
                      void QueueDestory(QUqueue* qu)//銷毀隊,防止內存泄漏
                      {
                      	queue* cur = qu->Dequeue;
                      	while (cur)
                      	{
                      		queue* pnext = cur->next;
                      		free(cur);
                      		cur = pnext;
                      	}
                      	qu->Dequeue = qu->Enqueue = NULL;
                      }
                      void QueuePrint(QUqueue* qu)//打印隊列中的元素,但前提是要出隊才能得到元素
                      {
                      	queue* cur = qu->Dequeue;
                      	while (cur)
                      	{
                      		printf("%d ", cur->data);
                      		cur = cur->next;
                      	}
                      }

                      隊 畢竟是先入先出的數據結構。
                      所以要兩個指針,
                      qu->Dequeue 指向隊頭,
                      qu->Enqueue 指向隊尾,
                      不然每次都去找隊尾是相當浪費時間的。

                      一個結構體類型用于維護這個隊列

                      typedef int QUData;
                      typedef struct queue//描述每個隊的元素
                      {
                      	QUData data;
                      	struct queue* next;
                      }queue;
                      typedef struct Queue//結構體用于維護隊列
                      {
                      	queue* Dequeue;//隊頭指針
                      	queue* Enqueue;//隊尾指針
                      }QUqueue;

                      隊頭指針負責出隊,
                      隊尾指針負責入隊。

                      概念流程圖

                      入隊

                      C語言數據結構的棧和隊列詳解

                      C語言數據結構的棧和隊列詳解

                      C語言數據結構的棧和隊列詳解

                      C語言數據結構的棧和隊列詳解

                      入隊列的實現

                      void QueuePush(QUqueue* qu, QUData n)//元素入隊
                      {
                      	queue* newcell = (QUData*)malloc(sizeof(QUData));
                      	newcell->data = n;
                      	newcell->next = NULL;
                      	if (qu->Dequeue == NULL)
                      	{
                      		qu->Enqueue = qu->Dequeue = newcell;
                      	}
                      	else
                      	{
                      		qu->Enqueue->next = newcell;
                      		qu->Enqueue = newcell;
                      	}
                      }

                      **當然,入隊列在剛開始的時候,頭尾指針還是一起指向NULL。
                      當入第一個元素時,那個元素即是第一個元素也是最后一個元素。要獨立判斷。**這是一個特殊情況。

                      出隊

                      C語言數據結構的棧和隊列詳解

                      C語言數據結構的棧和隊列詳解

                      C語言數據結構的棧和隊列詳解

                      出隊列的實現

                      QUData QueuePop(QUqueue* qu)//元素出隊
                      {
                      	if (QueueEmpty(qu))
                      	{
                      		printf("Queue Is Empty");
                      		exit(-1);
                      	}
                      	QUData ret = qu->Dequeue->data;
                      	qu->Dequeue = qu->Dequeue->next;
                      	return ret;
                      }

                      但是每次出隊列都需要判斷是否為空隊。如果是空隊還繼續出隊會相當于NULL->next ,這是直接報錯的。

                      所以還要一個函數判斷是否空隊。

                      是否空隊

                      int QueueEmpty(QUqueue* qu)//判斷隊列是否為空
                      {
                      	if (qu->Dequeue == qu->Enqueue)
                      		return 1;
                      	return 0;
                      }

                      空隊就是相當于回到了初始化的情形

                      qu->Dequeue = qu->Enqueue = NULL;

                      也就是兩者都指向同一處,也就是NULL。

                      到此,關于“C語言數據結構的棧和隊列詳解”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

                      向AI問一下細節

                      免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

                      AI

                      肥城市| 噶尔县| 平顺县| 黑水县| 城口县| 阳新县| 景洪市| 晋州市| 安义县| 上高县| 饶平县| 大足县| 韶山市| 巴青县| 威远县| 师宗县| 柘城县| 婺源县| 鸡西市| 云林县| 贡嘎县| 绥棱县| 合作市| 伊川县| 红桥区| 黎平县| 西乌珠穆沁旗| 三河市| 余江县| 游戏| 泗阳县| 宜良县| 河西区| 乌拉特后旗| 三亚市| 安国市| 三门县| 汾西县| 洮南市| 万安县| 西丰县|