Stories

Detail Return Return

棧的兩種存儲結構(順序存儲和鏈式存儲) - Stories Detail

棧的操作實現

棧的概念

棧是一種後進先出(LIFO)的線性數據結構,只允許在一端(棧頂)進行插入和刪除操作。新元素總是添加到棧頂,而刪除也總是從棧頂移除最上面的元素。棧常用於函數調用、表達式求值、括號匹配等場景。

代碼實現---順序存儲(Array-based Stack)

#include <stdio.h>	// 標準輸入輸出庫,用於 printf 等函數
#include <stdbool.h>// 布爾類型庫,提供 bool、true、false
#include <stdlib.h> // 標準庫,提供 malloc/calloc/free 和 exit 等函數

// 定義棧元素的類型為 int
typedef int DataType_t; 

// 定義棧的元素結構體
typedef struct SequenceStack 
{
	DataType_t *Bottom;
	unsigned int Size;
	int 		 Top;
} SeqStack_t;

SeqStack_t* SeqStack_init(unsigned int size)
{
	//calloc 返回的是 void * 類型指針,可以隱式轉換為任何其他指針類型(如 int*、char*),所以強制類型轉換不是必須的
	SeqStack_t *Manager = (SeqStack_t *)calloc(1,sizeof(SeqStack_t));

	if(Manager == NULL){
		perror("calloc for Manager is failed!\n");
		exit(-1);
	}

	Manager->Bottom = (DataType_t *)calloc(size,sizeof(DataType_t));
	
	if(Manager->Bottom == NULL){
		perror("calloc for stackEelement is failed\n");
		free(Manager);
		exit(-1);
	}

	Manager->Size = size; 
	Manager->Top = -1;//沒有元素,初始化為-1,新增一個元素後下標就可以等於0

	return Manager;
}
//判斷棧是不是滿
bool SeqStackIsfull(SeqStack_t *Manager)
{
	//假設stacksize是8,Top的值已經為7,則棧滿
	return (Manager->Top+1 == Manager->Size)?true:false;

}

//判斷棧是不是空
bool SeqStackIsEmpty(SeqStack_t *Manager)
{
	//Top初始值為-1,下次判斷依然是-1則棧是空
	return (Manager->Top == -1)?true:false;

}
//入棧
bool SeqStack_Push(SeqStack_t *Manager,DataType_t data)
{	
	//添加元素需要先判斷棧有沒有滿
	if(SeqStackIsfull(Manager)){
		printf("SeqStack is Full!\n");
		return false;
	}

	Manager->Bottom[++Manager->Top] = data;

	return true;

}
//出棧
DataType_t SeqStack_Pop(SeqStack_t *Manager)
{
	if (SeqStackIsEmpty(Manager)) {
    printf("SeqStack is Empty!\n");
    return; 
	}
	//棧頂元素出棧,Top-1
	DataType_t temp = Manager->Bottom[Manager->Top--];
	
	return temp; 

}
//遍歷棧
void SeqStack_Print(SeqStack_t *Manager)
{
	for(int i=0;i<= Manager->Top;i++){
		printf("Stack Element[%d] = %d\n",i,Manager->Bottom[i]);
	}
}


int main(int argc, char const *argv[])
{
    // 初始化大小為 4 的棧
    SeqStack_t *stack = SeqStack_init(4);

    // 測試空棧出棧
    printf("嘗試從空棧出棧:\n");
    SeqStack_Pop(stack);

    // 入棧測試
    printf("入棧: 10, 20, 30\n");
    SeqStack_Push(stack, 10);
    SeqStack_Push(stack, 20);
    SeqStack_Push(stack, 30);

    // 打印棧
    printf("當前棧內容:\n");
    SeqStack_Print(stack);

    // 測試棧滿
    printf("繼續入棧: 40, 50\n");
    SeqStack_Push(stack, 40);
    SeqStack_Push(stack, 50);  // 應提示棧滿

    // 出棧兩次
    printf("出棧兩次:\n");
    printf("出棧元素: %d\n", SeqStack_Pop(stack));
    printf("出棧元素: %d\n", SeqStack_Pop(stack));

    // 再打印棧
    printf("出棧後內容:\n");
    SeqStack_Print(stack);

    return 0;
}

運行結果

vmware_Tx2vRjXO8d

代碼實現---鏈式存儲(Linked Stack)

/**
 * @fire name:Linkedstack.c
 * @brief:/**
 * @fire name:SeqList.c
 * @brief:這個程序實現棧的入棧、出棧(鏈式存儲)
 * @author:13642563766@163.com
 * @date:2025/7/18
 * @version:1.0
 *  @note:None
 * Copyright (c)  2021-2022  13642563766@163.com  All right Reserved
 */

#include <stdio.h>
#include <stdlib.h>
// 定義棧中存儲的數據類型為 int
typedef int DataType;

// 鏈棧的節點結構體:每個節點包含數據和指向下一個節點的指針
typedef struct StackNode {
	DataType	data;
	struct StackNode *next;
}StackNode;

// 鏈棧管理結構體:用於管理整個棧的狀態
typedef struct{
	int size;
	StackNode *top;// 指向棧頂節點的指針(NULL 表示空棧)
}LinkedStack;

// 為 LinkedStack* 定義別名 Stack,表示一個棧的指針
typedef LinkedStack* Stack;

/**
 * 初始化棧
 * @param s 指向棧指針的指針(二級指針),用於返回棧的地址
 * @return 成功返回 1,失敗返回 0
 */
int InitStack(Stack *s)
{
	*s = (Stack)malloc(sizeof(LinkedStack));
	if(*s == NULL){
		return 0;
	}
	(*s)->top = NULL;
	(*s)->size = 0;
	return 1;
}

/**
 * 入棧操作:將一個新元素壓入棧頂
 * @param s 棧指針
 * @param data 要入棧的數據
 * @return 成功返回 1,失敗返回 0
 */
int Push(Stack s, DataType data) 
{
	if (s == NULL) {
        return 0; // 指針無效
    }

    StackNode *newNode = (StackNode*)malloc(sizeof(StackNode));
    if (newNode == NULL) {
        return 0; // 指針無效
    }
    // 設置新節點的數據和指針
    newNode->next = s->top;/
    newNode->data = data;
    s->top = newNode;//更新top指向新結點
    s->size++;//每入棧一個元素size++
    return 1;
}

/**
 * 出棧操作:彈出棧頂元素,並通過指針返回其值
 * @param s 棧指針
 * @param data 用於接收出棧元素值的輸出參數
 * @return 成功返回 1,棧為空或指針無效返回 0
 */
int Pop(Stack s, DataType *data)
{
	if(s == NULL || s->top == NULL){
		return 0; // 棧為空或棧指針無效,無法出棧
	}
    // 保存當前棧頂節點,便於後續釋放
	StackNode *Temp = s->top;
    // 將棧頂指針移動到下一個節點
	s->top = s->top->next;
	*data = Temp->data;
	free(Temp);
	s->size--;
	return 1;
}

//獲得棧頂元素的值
int GetTop(Stack s, DataType *data)
{
	if(s == NULL || s->top == NULL){
		return 0; // 棧為空或棧指針無效
	}
	*data = s->top->data;
	return 1;
}

int IsEmpty(Stack s) 
{
	if(s == NULL){
		 return 1;
	}

	return(s->top == NULL);
}

/**
 * 銷燬整個棧,釋放所有內存
 * @param s 指向棧的指針的指針
 */
void DestroyStack(Stack *s) {
    if (s == NULL || *s == NULL) {
        return;
    }

    StackNode *current = (*s)->top;
    StackNode *next;
    // 逐個釋放節點
    while (current != NULL) {
        next = current->next;
        free(current);
        current = next;
    }
    // 釋放棧結構本身
    free(*s);
    *s = NULL; // 防止野指針
}

int main() {
    Stack myStack;
    DataType value;

    // 1. 初始化棧
    if (!InitStack(&myStack)) {
        printf("初始化棧失敗!\n");
        return -1;
    }
    printf("棧初始化成功。\n");

    // 2. 入棧操作
    printf("入棧: 10, 20, 30\n");
    Push(myStack, 10);
    Push(myStack, 20);
    Push(myStack, 30);

    // 3. 查看棧頂元素
    if (GetTop(myStack, &value)) {
        printf("當前棧頂元素: %d\n", value);
    } else {
        printf("棧為空,無法獲取棧頂元素。\n");
    }

    // 4. 出棧操作
    printf("開始出棧:\n");
    while (!IsEmpty(myStack)) {
        if (Pop(myStack, &value)) {
            printf("彈出: %d\n", value);
        }
    }

    // 5. 再次嘗試出棧 (棧已空)
    if (Pop(myStack, &value)) {
        printf("彈出: %d\n", value);
    } else {
        printf("棧已空,無法彈出元素。\n");
    }

    // 6. 銷燬棧
    DestroyStack(&myStack);
    printf("棧已銷燬。\n");

    return 0;
}

運行結果

vmware_NkA6WEPdAD

user avatar Zeeh-Lin Avatar Invinc-Z Avatar
Favorites 2 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.