基本的抽象資料型別(adt)是編寫c程式必要的過程,這類adt有鍊錶、堆疊、佇列和樹等,本文主要講解下堆疊的幾種實現方法以及他們的優缺點。
堆疊(stack)的顯著特點是後進先出(last-in first-out, lifo),其實現的方法有三種可選方案:靜態陣列、動態分配的陣列、動態分配的鏈式結構。
靜態陣列:特點是要求結構的長度固定,而且長度在編譯時候就得確定。其優點是結構簡單,實現起來方便而不容易出錯。而缺點就是不夠靈活以及固定長度不容易控制,適用於知道明確長度的場合。
動態陣列:特點是長度可以在執行時候才確定以及可以更改原來陣列的長度。優點是靈活,缺點是由此會增加程式的複雜性。
鏈式結構:特點是無長度上線,需要的時候再申請分配記憶體空間,可最大程度上實現靈活性。缺點是鏈式結構的鏈結字段需要消耗一定的記憶體,在鏈式結構中訪問乙個特定元素的效率不如陣列。
首先先確定乙個堆疊介面的標頭檔案,裡面包含了各個方案下的函式原型,放在一起是為了實現程式的模組化以及便於修改。然後再接著分別介紹各個方案的具體實施方法。
堆疊介面stack.h檔案**:
[cpp]view plain
copy
/*** 堆疊模組的介面 stack.h
*/#include
#define stack_type int /* 堆疊所儲存的值的資料型別 */
/*** 函式原型:create_stack
** 建立堆疊,引數指定堆疊可以儲存多少個元素。
** 注意:此函式只適用於動態分配陣列形式的堆疊。
*/void create_stack(size_t size);
/*** 函式原型:destroy_stack
** 銷毀乙個堆疊,釋放堆疊所適用的記憶體。
** 注意:此函式只適用於動態分配陣列和鏈式結構的堆疊。
*/void destroy_stack(void);
/*** 函式原型:push
** 將乙個新值壓入堆疊中,引數是被壓入的值。
*/void push(stack_type value);
/*** 函式原型:pop
** 彈出堆疊中棧頂的乙個值,並丟棄。
*/void pop(void);
/*** 函式原型:top
** 返回堆疊頂部元素的值,但不改變堆疊結構。
*/stack_type top(void);
/*** 函式原型:is_empty
** 如果堆疊為空,返回true,否則返回false。
*/int is_empty(void);
/*** 函式原型:is_full
** 如果堆疊為滿,返回true,否則返回false。
*/int is_full(void);
一、靜態陣列堆疊
在靜態陣列堆疊中,stack_size表示堆疊所能儲存的元素的最大值,用top_element作為陣列下標來表示堆疊裡面的元素,當top_element == -1的時候表示堆疊為空;當top_element == stack_size - 1的時候表示堆疊為滿。push的時候top_element加1,top_element == 0時表示第乙個堆疊元素;pop的時候top_element減1。
a_stack.c 源**如下:
[cpp]view plain
copy
/***
** 靜態陣列實現堆疊程式 a_stack.c ,陣列長度由#define確定
*/#include"stack.h"
#include
#include
#define stack_size 100 /* 堆疊最大容納元素數量 */
/*** 儲存堆疊中的陣列和乙個指向堆疊頂部元素的指標
*/static stack_type stack[stack_size];
static
int top_element = -1;
/* push */
void push(stack_type value)
/* pop */
void pop(void)
/* top */
stack_type top(void)
/* is_empty */
int is_empty(void)
/* is_full */
int is_full(void)
/*** 定義乙個print函式,用來列印堆疊裡面的元素。
*/void print(void)
int main(void)
結果如下圖:
二、動態陣列堆疊
標頭檔案還是用stack.h,改動的並不是很多,增加了stack_size變數取代stack_size來儲存堆疊的長度,陣列由乙個指標來代替,在全域性變數下預設為0。
create_stack函式首先檢查堆疊是否已經建立,然後才分配所需數量的記憶體並檢查分配是否成功。destroy_stack函式首先檢查堆疊是否存在,已經釋放記憶體之後把長度和指標變數重新設定為零。is_empty 和 is_full 函式中新增了一條斷言,防止任何堆疊函式在堆疊被建立之前就被呼叫。
d_stack.c源**如下:
[cpp]view plain
copy
/*** 動態分配陣列實現的堆疊程式 d_stack.c
** 堆疊的長度在建立堆疊的函式被呼叫時候給出,該函式必須在任何其他操作堆疊的函式被呼叫之前條用。
*/#include"stack.h"
#include
#include
#include
/*** 用於儲存堆疊元素的陣列和指向堆疊頂部元素的指標
*/static stack_type *stack;
static
int stack_size;
static
int top_element = -1;
/* create_stack */
void create_stack(size_t size)
/* destroy */
void destroy_stack(void)
/* push */
void push(stack_type value)
/* pop */
void pop(void)
/* top */
stack_type top(void)
/* is_empty */
int is_empty(void)
/* is_full */
int is_full(void)
/*** 定義乙個print函式,用來列印堆疊裡面的元素。
*/void print(void)
int main(void)
結果如下圖:
三、鏈式堆疊
由於只有堆疊頂部元素才可以被訪問,因此適用單鏈表可以很好實現鏈式堆疊,而且無長度限制。把乙個元素壓入堆疊是通過在鍊錶頭部新增乙個元素實現。彈出乙個元素是通過刪除鍊錶頭部第乙個元素實現。由於沒有長度限制,故不需要create_stack函式,需要destroy_stack進行釋放記憶體以避免記憶體洩漏。
標頭檔案stack.h 不變,l_stack.c 源**如下:
[cpp]view plain
copy
/*** 單鏈表實現堆疊,沒有長度限制
*/#include"stack.h"
#include
#include
#include
#define false 0
/*** 定義乙個結構以儲存堆疊元素。
*/typedef
struct stack_node
stacknode;
/* 指向堆疊中第乙個節點的指標 */
static stacknode *stack;
/* create_stack */
void create_stack(size_t size)
{}
/* destroy_stack */
void destroy_stack(void)
/* push */
void push(stack_type value)
/* pop */
void pop(void)
/* top */
stack_type top(void)
/* is_empty */
int is_empty(void)
/* is_full */
int is_full(void)
/*** 定義乙個print函式,用來列印堆疊裡面的元素。
*/void print(void)
printf("\n");
} int main(void)
結果如下圖:
實現氣泡排序方法C語言版
花哥哥的瞎說 所謂的氣泡排序,就是把最大或者最小的往上冒,也就是往後陣列後面走,把陣列分為兩個區,乙個是待排序區,乙個是已經排序好的區,哎呀,真的說著我自己都亂了。簡單的小例項 for i 0 i 10 i 注意 我們認為第乙個元素是有序,從後面的元素依次跟它比較,每次都是有序區的最後乙個元素,與無...
Sunday演算法c語言版實現
一 bf演算法 bf演算法是普通的模式匹配演算法,其基本思想就是將目標串的第乙個字元與模式串的第乙個字元進行匹配。若相等,則繼續比較第二個字元 若不相等,則比較目標串的第二個字元和模式串的第乙個字元。依次比較下去,直到得出最後的匹配結果。示例 static int bf const char src...
迴圈佇列的實現(C語言版)
執行環境 vs2015 include include include 定義 typedef int elemtype typedef int status 定義常量的值 define ok 1 define error 0 define true 1 define false 0 define o...