【數據結構】使用C語言 從零實現一個棧的數據結構

什么是棧?棧是一種特殊的線性表,它只能在在表尾進行插入和刪除操作。

棧的底部稱為棧底,頂部稱為棧頂,所有的操作只能在棧頂進行,也就是說,被壓在下方的元素,只能等待其上方的元素出棧之后才能取出,就像我們往箱子里里面放的書一樣,因為只有一個口取出里面的物品,所以被壓在下面的書只能等上面的書被拿出來之后才能取出,這就是棧的思想,它是一種先進后出的數據結構。

使用C語言實現棧

一般使用棧這樣的機構,常用的兩個操作就是入棧和出棧

  • pop:出棧操作,將棧頂的元素取出,并刪除
  • push:入棧操作,將新元素置入棧頂

定義數據結構

我們在棧的底層使用數組進行存儲,所以結構中將儲存一個數組的指針,和數組的容量(方便初始化和申請內存);另外棧只能操作棧頂的元素,所以結構中還存著一個變量top,表示棧頂的元素。

typedef int E;struct Stack
{E * array; // 一個數組的指針int capacity; // 數組的容量int top;  // 棧頂的元素
};typedef struct Stack * stack;

再給棧結構的指針起一個別名,便于后續對棧進行操作。

定義初始化方法

接著我們定義一個初始化棧的方法,在初始化方法中,我們默認初始化時,底層數組的最大容量是10個內存單位,也就是40字節(因為E是int類型),接著我們定義,剛初始化完棧之后是一個空棧,則棧頂的指針默認為-1。

top變量是為后續的入棧出棧操作做鋪墊的,它可以當作數組的索引,也可以用來當作是否是空棧的標識。

int initStack(stack stack)
{stack->array = malloc(sizeof(E) * 10); // 申請一個40字節的內存if (stack->array == NULL) return 0;stack->capacity = 10; // 記錄底層數組的容量stack->top = -1;  // 棧沒有元素默認為-1return 1;
}

在main函數中,實例化一個Stack類型,接著使用initStack函數就完成了棧的初始化:

int main()
{struct Stack stack;initStack(&stack);return 0;
}

實現入棧操作

入棧操作,就是把一個元素放到棧的最上方,也就是棧頂上,所以實現該操作的函數只需要有兩個參數就可以了:

  • 棧的指針
  • 需要入棧的元素

另外,底層數組的默認容量是10,如果入棧超過10個元素的話,內存就會造成泄露,所以對底層數組進行擴容操作也是必不可少的。

int pushStack(stack stack,E element)
{if (stack->top == stack->capacity - 1) // 擴容{int newCapacity = stack->capacity * 2;E* newArray = realloc(stack->array,newCapacity * sizeof(E));if (newArray == NULL) return 0;stack->array = newArray;stack->capacity = newCapacity;}stack->top++;stack->array[stack->top] = element;return 1;
}

在擴容操作中,我們使用realloc函數將原數組拷貝到一個新的大小的內存中,這個內存地址我們使用newArray來接收,最后將原棧中的array指向newArray,將原棧中的capacity 指向newCapacity

簡單編寫一個打印棧元素的函數,用于測試棧:

void printStack(stack stack)
{printf("|");for (int i = 0;i<=stack->top;i++){printf("%d, ",stack->array[i]);}printf("\n");
}int main()
{struct Stack stack;initStack(&stack);for(int i = 1;i<=10;i++){pushStack(&stack,i);}printStack(&stack);return 0;
}

控制臺輸出:

|1, 2, 3, 4, 5, 6, 7, 8, 9, 10,

入棧操作成功實現~

實現出棧操作

出棧操作就是把棧頂的元素取出,然后把top執行自減操作,如果不自減元素出棧之后棧頂的元素還會是原來的元素。

E popStack(stack stack)
{if (stack->top == -1){printf("棧為空,不能出棧\n");return -1;}E element = stack->array[stack->top];stack->top--;return element;
}

我們接著測試一下:

void printStack(stack stack)
{printf("|");for (int i = 0;i<=stack->top;i++){printf("%d, ",stack->array[i]);}printf("\n");
}int main()
{struct Stack stack;initStack(&stack);for(int i = 1;i<=20;i++){pushStack(&stack,i);}printStack(&stack);printf("出棧的元素順序:");while (1){printf("%d, ",stack.array[stack.top]);popStack(&stack);if (stack.top == -1) break;}return 0;
}

會發現控制臺輸出的信息為:

|1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
出棧的元素順序:20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,

出棧的順序是從20到1的,說明元素是從棧頂依次出去的,至此出棧操作也實現好了。

總結

使用C語言手動把棧的結構和各種操作實現一遍是很重要的,它能夠加深學習者對計算機底層的認識,也能夠為后續的算法題的解題提供一種新的思路。

本篇博文所有代碼:

#include "stdio.h"
#include "stdlib.h"typedef int E;struct Stack
{E * array; // 一個數組的指針int capacity; // 數組的容量int top;  // 棧頂的元素
};typedef struct Stack * stack;int initStack(stack stack)
{stack->array = malloc(sizeof(E) * 10); // 申請一個40字節的內存if (stack->array == NULL) return 0;stack->capacity = 10; // 記錄底層數組的容量stack->top = -1;  // 棧沒有元素默認為-1return 1;
}int pushStack(stack stack,E element)
{if (stack->top == stack->capacity - 1) // 擴容{int newCapacity = stack->capacity * 2;E* newArray = realloc(stack->array,newCapacity * sizeof(E));if (newArray == NULL) return 0;stack->array = newArray;stack->capacity = newCapacity;}stack->top++;stack->array[stack->top] = element;return 1;
}E popStack(stack stack)
{if (stack->top == -1){printf("棧為空,不能出棧\n");return -1;}E element = stack->array[stack->top];stack->top--;return element;
}void printStack(stack stack)
{printf("|");for (int i = 0;i<=stack->top;i++){printf("%d, ",stack->array[i]);}printf("\n");
}int main()
{struct Stack stack;initStack(&stack);for(int i = 1;i<=20;i++){pushStack(&stack,i);}printStack(&stack);printf("出棧的元素順序:");while (1){printf("%d, ",stack.array[stack.top]);popStack(&stack);if (stack.top == -1) break;}return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/40214.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/40214.shtml
英文地址,請注明出處:http://en.pswp.cn/web/40214.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LeetCode-簡單-回文數

給你一個整數 x &#xff0c;如果 x 是一個回文整數&#xff0c;返回 true &#xff1b;否則&#xff0c;返回 false 。 回文數 是指正序&#xff08;從左向右&#xff09;和倒序&#xff08;從右向左&#xff09;讀都是一樣的整數。 例如&#xff0c;121 是回文&#xff0c;…

windows啟動Docker閃退Docker desktop stopped

Windows啟動Docker閃退-Docker desktop stopped 電腦上很早就安裝有Docker了&#xff0c;但是有一段時間都沒有啟動了&#xff0c;今天想啟動啟動不起來了&#xff0c;打開沒幾秒就閃退&#xff0c;記錄一下解決方案。僅供參考 首先&#xff0c;參照其他解決方案&#xff0c;本…

Ubuntu20安裝mysql方法,適用于wsl

itopen組織1、提供OpenHarmony優雅實用的小工具2、手把手適配riscv qemu linux的三方庫移植3、未來計劃riscv qemu ohos的三方庫移植 小程序開發4、一切擁抱開源&#xff0c;擁抱國產化 一、Ubunt20安裝mysql 適用于wsl中安裝mysql sudo apt update# 查看可使用的安裝包…

【刷題匯總--游游的you、腐爛的蘋果、孩子們的游戲(圓圈中最后剩下的數)】

C日常刷題積累 今日刷題匯總 - day0051、游游的you1.1、題目1.2、思路1.3、程序實現 - 蠻力法1.4、程序實現 - 貪心(優化) 2、腐爛的蘋果2.1、題目2.2、思路2.3、程序實現 - bfs 3、孩子們的游戲(圓圈中最后剩下的數)3.1、題目3.2、思路3.3、程序實現 -- 環形鏈表3.4、程序實現…

2個方法教你輕松移除pdf文件編輯限制

PDF是一種常見的辦公文檔格式&#xff0c;常用于文件共享和保護。然而&#xff0c;有時候我們需要編輯PDF文件中的內容&#xff0c;但受到了編輯限制。本文將介紹一些有效的方法&#xff0c;幫助您解除PDF的編輯限制&#xff0c;輕松進行編輯和修改。 一、通過密碼取消PDF“限制…

雷電模擬器報錯remount of the / superblock failed: Permission denied remount failed

報錯截圖 解決方法 打開設置 設置配置system.vmdk可寫入 解決

Transformer和Mamba強強結合!最新混合架構全面開源,推理速度狂飆8倍

最近發現&#xff0c;將Mamba和Transformer模塊混合使用&#xff0c;效果會比單獨使用好很多&#xff0c;這是因為該方法結合了Mamba的長序列處理能力和Transformer的建模能力&#xff0c;可以顯著提升計算效率和模型性能。 典型案例如大名鼎鼎的Jamba&#xff1a;Jamba利用Tr…

ELK優化之Elasticsearch

目錄 1.ELK優化 2.優化 ES 索引設置 2.1 優化 fsync 2.2 優化 refresh 2.3 優化 merge 2.4 優化設置 2.5 打開索引 3.優化線程池配置 3.1 優化的方案 4.鎖定內存&#xff0c;不讓 JVM 使用 Swap 5.減少分片數、副本數 6.ES優化總結 1.ELK優化 ELK優化可以圍繞著 li…

Python統計實戰:時間序列分析之簡單指數平滑和Holt指數平滑

為了解決特定問題而進行的學習是提高效率的最佳途徑。這種方法能夠使我們專注于最相關的知識和技能&#xff0c;從而更快地掌握解決問題所需的能力。 &#xff08;以下練習題來源于《統計學—基于Python》。請在Q群455547227下載原始數據。&#xff09; 練習題 下表是某只股票…

二維平面無中心點的聚類算法

問題描述 二維平面上有許多點p(x , y)&#xff0c;按照彼此之間的歐式距離進行分為若干個集合。若點p1(x1, y1)與點p(x2, y2)之間距離小于d,則認為二者是鄰居。 算法思路 給數據集的點進行編號&#xff0c;順序遍歷這些點&#xff0c;找出當前點的鄰居&#xff0c;記住已經遍…

模具監視器的選擇要點介紹

模具監視器的選擇要點涉及多個方面&#xff0c;以確保其能夠滿足實際生產需求并提高生產效率。以下是一些關鍵的選擇要點&#xff1a; 一、性能和穩定性 監控精度&#xff1a;選擇模具監視器時&#xff0c;首先要考慮其監控精度&#xff0c;包括溫度、壓力、注射速度等參數的…

Debezium系列之:JVM參數詳解和Debezium集群JVM監控看板制作

Debezium系列之:JVM參數詳解和Debezium集群JVM監控看板制作 一、JVM參數詳解1.jvm_memory_bytes_used2.jvm_memory_bytes_committed3.jvm_memory_bytes_max4.jvm_memory_bytes_init5.jvm_memory_pool_bytes_used6.jvm_memory_pool_bytes_committed7.jvm_memory_pool_bytes_max…

金屬3D打印如何精準選材

隨著3D打印技術的飛躍發展&#xff0c;模具制造領域迎來了前所未有的創新機遇。在眾多3D打印技術中&#xff0c;SLM金屬3D打印以其精度高、復雜結構成型能力&#xff0c;成為眾多行業的優選。然而&#xff0c;金屬打印材料&#xff0c;如何精準選擇&#xff0c;以最大化滿足項目…

linux 內核打印log太多咋辦?

有時候發現&#xff0c;linux 內核打印太多消息了&#xff0c;對有用消息造成了干擾&#xff0c;如果你一個個源文件去關閉打印太麻煩了&#xff0c;有沒有一種更方便的方式來關閉這些消息呢&#xff1f; 對這個需求&#xff0c;內核提供了一個強大而又靈活的方式&#xff0c;…

開源 WAF 解析:選擇最適合你的防護利器

前言 隨著網絡安全風險的增加&#xff0c;Web 應用防火墻&#xff08;WAF&#xff09;成為保護網站和應用程序免受攻擊的關鍵工具。在眾多的選擇中&#xff0c;開源 WAF 以其靈活性、可定制性和成本效益備受青睞。本文將深入探討幾種主流開源 WAF 解決方案&#xff0c;幫助你選…

用html+css設計一個列表清單小卡片

目錄 簡介: 效果圖: 源代碼: 可能的問題: 簡介: 這個HTML代碼片段是一個簡單的列表清單設計。它包含一個卡片元素(class為"card"),內部包含一個無序列表(ul),列表項(li)前面有一個特殊的符號(△)。整個卡片元素設計成300px寬,150px高,具有圓角邊…

從0-1配置一個ROS項目

目標&#xff1a;從0-1配置一個ROS項目&#xff0c;實現hello,world打印&#xff0c;在此基礎上進行功能開發。 步驟1&#xff1a;創建工作空間&#xff1a; mkdir -p ros_workspace/src cd ros_workspace對工作空間進行初始化&#xff1a; catkin_make source devel/setup.…

20.【C語言】初識結構體(重要)

定義&#xff1a;由一批數據組合而成的結構型數據 作用&#xff1a;描述復雜對象&#xff0c;創建新的類型 格式&#xff1a; struct 對象 { …… } 介紹. 用法&#xff1a;結構體變量.成員變量 #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> struct hotal…

代碼隨想錄訓練營Day57

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 前言一、X的平方根二、有效的完全平方數 前言 提示&#xff1a;這里可以添加本文要記錄的大概內容&#xff1a; 今天是跟著代碼隨想錄刷題的第57天&#xff0c;繼…

Prompt-Free Diffusion: Taking “Text” out of Text-to-Image Diffusion Models

CVPR2024 SHI Labshttps://arxiv.org/pdf/2305.16223https://github.com/SHI-Labs/Prompt-Free-Diffusion 問題引入 在SD模型的基礎之上&#xff0c;去掉text prompt&#xff0c;使用reference image作為生成圖片語義的指導&#xff0c;optional structure image作為生成圖片…