數據結構(4)—棧和隊列

一、概念

1.棧只允許在棧頂位置入棧和出棧元素,鏈表可以在任意位置插入和刪除元素,棧和隊列只允許在指定位置插入和刪除元素

2.鏈表、棧和隊列都是一種線性結構(一對一),棧和隊列是一種特殊的表狀結構

二、棧

1.基礎概念

先進后出,后進先出

棧頂:允許入棧和出棧的一端稱為棧頂

棧底:不允許入棧和出棧的一端稱為棧底

入棧(壓棧):將元素放入棧頂位置

出棧(彈棧):將棧頂元素取出

棧針:記錄棧頂位置的標記

2.分類:

(1)順序棧:

增棧:棧的方向自低向高增長? ? 減棧:棧的方向自高向低增長

空棧:棧針指向要入棧的位置? ? 滿棧:棧針指向棧頂元素的位置

常見順序棧:?空增棧、空減棧、滿增棧、滿減棧

此圖為空減棧

①順序棧的實現

#ifndef __SEQSTACK_H__
#define __SEQSTACK_H__
typedef int datatype;???????????????? //存放數據的類型
typedef struct stack
{
datatype *pdata; ??????????????//存放數據空間首地址
int top;??????????????????????????????//棧頂元素位置
int tlen;?????????????????????????????//最多存放元素個數
}seqstack;
#endif

②順序棧的創建

申請存放標簽的空間,申請存放數據的空間

seqstack *create_seqstack(int len)
{
seqstack *ptmpstack = NULL;
//申請標簽空間
ptmpstack = malloc(sizeof(seqstack));
if (NULL == ptmpstack)
{
perror("fail to malloc");
return NULL;
}
//申請存放數據的空間
ptmpstack->pdata = malloc(sizeof(datatype) * len);
if (NULL == ptmpstack->pdata)
{
perror("fail to malloc");
return NULL;
}
ptmpstack->top = 0;
ptmpstack->tlen = len;
return ptmpstack;
}

③ 順序棧的銷毀:

銷毀存放數據的空間,銷毀存放標簽的空間

int destroy_seqstack(seqstack **pptmpstack)
{
free((*pptmpstack)->pdata);
free((*pptmpstack));
*pptmpstack = NULL;
return 0;
}

(注意先后順序)

④是否為空棧:棧針為0即為空棧

int is_empty_seqstack(seqstack *ptmpstack)
{
return 0 == ptmpstack->top;
}

⑤是否為滿棧:棧針與tlen相同即為滿棧

int is_full_seqstack(seqstack *ptmpstack)
{
return ptmpstack->tlen == ptmpstack->top;
}

⑥?壓棧:將元素放入棧頂位置,棧針位置++

int push_seqstack(seqstack *ptmpstack, datatype tmpdata)
{
if (is_full_seqstack(ptmpstack))
{
return -1;
}
ptmpstack->pdata[ptmpstack->top++] = tmpdata;
return 0;
}

⑦出棧:棧針位置--,將棧頂元素出棧

datatype pop_seqstack(seqstack *ptmpstack)
{
if (is_empty_seqstack(ptmpstack))
{
return -1;
}
return ptmpstack->pdata[--ptmpstack->top];
}

(2)鏈式棧

使用鏈表的思想實現鏈式棧,參考單向鏈表節點定義,壓棧使用頭插法,出棧返回鏈表第一個有效節點的值,并刪除該節點,在主函數循環出棧,銷毀棧參考單向鏈表的銷毀

linknode *create_empty_linkstack(void)
{
linknode *ptmpnode = NULL;
//創建空白節點
ptmpnode = malloc(sizeof(linknode));
if (NULL == ptmpnode)
{
perror("fail to malloc");
return NULL;
}

????????//初始化節點中的值
ptmpnode->pnext = NULL;
//返回空白節點地址
return ptmpnode;
}
/* 判斷順序棧是否為空 */
int is_empty_linkstack(linknode *phead)
{
//判斷空白節點后面還有沒有節點
return NULL == phead->pnext;
}

/* 壓棧 */
int push_linkstack(linknode *phead, datatype tmpdata)
{
linknode *ptmpnode = NULL;
//頭插法
ptmpnode = malloc(sizeof(linknode));
if (NULL == ptmpnode)
{
perror("fail to malloc");
return -1;
}
ptmpnode->data = tmpdata;
ptmpnode->pnext = phead->pnext;
phead->pnext = ptmpnode;
return 0;
}

/* 出棧 */
datatype pop_linkstack(linknode *phead)
{

????????datatype retval;
linknode *ptmpnode = NULL;
if (is_empty_linkstack(phead))
{
return -1;
}

????????//刪除第一個有效元素
ptmpnode = phead->pnext;
phead->pnext = ptmpnode->pnext;
retval = ptmpnode->data;
free(ptmpnode);
//返回數據
return retval;

}
/* 銷毀棧 */
int destroy_linkstack(linknode **pphead)
{
linknode *ptmpnode = NULL;
linknode *pfreenode = NULL;
ptmpnode = pfreenode = *pphead;
while (ptmpnode != NULL)
{
ptmpnode = ptmpnode->pnext;
free(pfreenode);
pfreenode = ptmpnode;
}
*pphead = NULL;
return 0;
}

三、隊列

1.基礎概念

先進先出,后進后出

隊頭:出隊的一端

隊尾:入隊的一端

入隊:將元素放入隊列末尾

?出隊:將元素從隊頭中取出

2.分類

(1)循環隊列

①定義

typedef int datatype;

typedef struct queue
{
datatype *pdata; ????????//存放數據空間的首地址
int head; ????????????????????//頭下標
int tail; ???????????????????????//尾下標
int tlen; ?????????????????????//最多存放元素個數
}seqqueuee

②循環隊列創建

seqqueue *create_seqqueue(int len)
{
seqqueue *ptmpqueue = NULL;
ptmpqueue = malloc(sizeof(seqqueue));
if (NULL == ptmpqueue)
{
perror("fail to malloc");
return NULL;
}
ptmpqueue->pdata = malloc(sizeof(datatype) * len);
if (NULL == ptmpqueue->pdata)
{
perror("fail to malloc");
return NULL;
}

????????ptmpqueue->head = 0;
ptmpqueue->tail = 0;
ptmpqueue->tlen = len;
return ptmpqueue;
}

③?循環隊列銷毀

int destroy_seqqueue(seqqueue **pptmpqueue)
{
free((*pptmpqueue)->pdata);
free(*pptmpqueue);
*pptmpqueue = NULL;
return 0;
}

④判斷循環隊列是否為空

int is_empty_seqqueue(seqqueue *ptmpqueue)
{
return ptmpqueue->head == ptmpqueue->tail;
}

⑤?判斷循環隊列是否為滿

1)為避免循環隊列空與滿的條件沖突,犧牲一個存放數據的空間,將tail+1 == head作為判斷隊滿的條件

2)循環隊列如果head或者tail下標超過tlen范圍,需要對tlen取余,保障head和tail的值在隊列下標范圍內變化

int is_full_seqqueue(seqqueue *ptmpqueue)
{
return ((ptmpqueue->tail + 1) % ptmpqueue->tlen) ==
ptmpqueue->head;
}

⑥入隊

int enter_seqqueue(seqqueue *ptmpqueue, datatype tmpdata)
{
if (is_full_seqqueue(ptmpqueue))
{
return -1;
}
ptmpqueue->pdata[ptmpqueue->tail] = tmpdata;
ptmpqueue->tail = (ptmpqueue->tail + 1) % ptmpqueue->tlen;
return 0;
}

⑦出隊

datatype quit_seqqueue(seqqueue *ptmpqueue)
{
datatype retval;
if (is_empty_seqqueue(ptmpqueue))
{
return -1;
}
retval = ptmpqueue->pdata[ptmpqueue->head];
ptmpqueue->head = (ptmpqueue->head + 1) % ptmpqueue->tlen;
return retval;
}

(2)鏈式隊列

使用鏈表的思想實現鏈式隊列,參考單向鏈表節點定義,入隊使用尾插法,出隊返回鏈表第一個有效節點的值,并刪除該節點,在主函數循環出棧隊,銷毀棧參考單向鏈表的銷毀

#include "linkstack.h"
#include <stdio.h>
#include <stdlib.h>

linknode *create_empty_linkstack(void)
{
linknode *ptmpnode = NULL;

? ? ptmpnode = malloc(sizeof(linknode));
if (NULL == ptmpnode)
{
perror("fail to malloc");
return NULL;
}

? ? ptmpnode->pnext = NULL;

? ? return ptmpnode;
}

int is_empty_linkstack(linknode *phead)
{
return NULL == phead->pnext;
}

int push_linkstack(linknode *phead, datatype tmpdata)
{
linknode *ptmpnode = NULL;

? ? ptmpnode = malloc(sizeof(linknode));
if (NULL == ptmpnode)
{
perror("fail to malloc");
return -1;
}

? ? ptmpnode->data = tmpdata;
ptmpnode->pnext = phead->pnext;
phead->pnext = ptmpnode;

? ? return 0;
}

datatype pop_linkstack(linknode *phead)
{
linknode *ptmpnode = NULL;
datatype tmpdata = 0;

? ? ptmpnode = phead->pnext;
tmpdata = ptmpnode->data;
phead->pnext = ptmpnode->pnext;
free(ptmpnode);
ptmpnode ?= phead->pnext;?

? ? return tmpdata;
}

int destory_linkstack(linknode **phead)
{
linknode *ptmpnode = NULL;
linknode *pprenode = NULL;

? ? ptmpnode = pprenode = *phead;
while(ptmpnode != NULL)
{
ptmpnode = ptmpnode->pnext;
free(pprenode);
pprenode = ptmpnode;
}
*phead = NULL;

? ? return 0;
}

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

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

相關文章

vue2.如何給一個頁面設置動態的name。不同路由使用一樣的組件。頁面不刷新怎么辦?

page里面detail.vue export default { name: detail, } vue2里面.vue的頁面都會設置一個name&#xff0c;這個通常是寫死的。不能在頁面動態設置的。頁面刷新緩存通常都是根據這個name來判斷的。如果name寫死。我幾個頁面都通用這一個頁面的話&#xff0c;他也不刷新頁面啊。 比…

浮動IP(Floating IP)的刪除通常需要滿足什么條件

浮動IP&#xff08;Floating IP&#xff09;的刪除通常需要滿足什么條件在云計算或網絡環境中&#xff0c;浮動IP&#xff08;Floating IP&#xff09;的刪除通常需要滿足一定的條件&#xff0c;以確保操作不會影響現有業務或導致網絡中斷。以下是常見的可刪除浮動IP的場景和條…

機器學習之隨機森林(Random Forest)實戰案例

一、算法基礎 首先&#xff0c;來介紹一下算法的基礎語法 class sklearn.ensemble.RandomForestClassifier(\ n_estimators’warn’,\ criterion’gini’,\max_depthNone, \ min_samples_split2,\ min_samples_leaf1, \ min_weight_fraction_leaf0.0, \ max_features’auto’…

《C語言》指針練習題--1

《C語言》指針練習題–1 1. 交換兩個整數的值 題目描述&#xff1a; 編寫一個C程序&#xff0c;定義一個函數swap&#xff0c;使用指針參數交換兩個整數的值。在main函數中調用該函數并輸出交換后的結果。 解題思路&#xff1a; 為了交換兩個整數的值&#xff0c;可以通過指針傳…

應急響應整理

目錄 windows下 1. 檢查賬號安全 利用注冊表實現用戶隱藏 粘滯鍵后門 2 檢查異常端口、進程 3. 檢查啟動項、計劃任務、服務 4. 日志分析-Windows 常見事件類型、登錄類型 Linux下 1. 賬號安全 2. 歷史命令 3. 檢查異常端口 4. 檢查異常進程 5. 檢查開機啟動項 …

一文讀懂 C# 中的 Bitmap

一文讀懂 C# 中的 Bitmap 一、Bitmap 到底是什么? 二、推薦使用場景 三、實戰 Demo 基礎用法:加載、創建和保存 進階用法 縮放圖片 裁剪圖片 顏色調整(反色處理) 四、核心方法和屬性說明 常用函數 常用屬性 五、避坑指南、注意事項 六、總結與決策 一文讀懂 C# 中的 Bitmap…

預約時間組件

效果圖如何使用<template><view><button click"pickerTime(0)">預約時間0</button><button click"pickerTime(1)">預約時間1</button><button click"pickerTime(2)">預約時間2</button><but…

Android 開發 - Service、Camera、Layout Design 自定義設備類型和大小

一、Service 啟動 1、基本介紹 &#xff08;1&#xff09;startService()其他組件通過調用 startService() 啟動 Service 后&#xff0c;Service 可在后臺無限期運行&#xff0c;即使啟動 Service 的組件被銷毀也不受影響&#xff0c;一般情況下 startService() 是執行單一操作…

Qwen Image:開源中文渲染SOTA,重塑文生圖技術邊界

1. Qwen Image的技術定位與行業痛點1.1 文本渲染&#xff1a;文生圖領域的長期技術瓶頸傳統文生圖模型在圖像美學與真實感優化上已取得顯著進展&#xff0c;但多語言文本渲染始終是行業難以突破的瓶頸。主流模型在處理中文等非字母語言時&#xff0c;常出現字符斷裂、布局錯位、…

Docker入門教程:在騰訊云輕量服務器上部署你的第一個容器化應用 (2025)

更多云服務器知識&#xff0c;盡在hostol.com“在我電腦上明明是好的啊&#xff01;”這句話&#xff0c;是不是堪稱程序員“甩鍋”排行榜第一名的金句&#xff1f;當你辛辛苦苦開發完一個應用&#xff0c;把它交給同事或者部署到服務器上時&#xff0c;卻發現因為它依賴的某個…

DevOps平臺結合Gradle實現打包流水線

在現代軟件開發中,持續集成與持續交付(CI/CD)已成為團隊提速、降本增效的核心實踐。Gradle作為強大的自動化構建工具,常被用于Android與Java項目的構建打包任務。而將Gradle集成進企業的DevOps平臺中,不僅可以標準化構建過程,還能自動化打包、測試、發布的全流程,大幅提…

Node.js 操作 MySQL

目錄 一、什么是 MySQL&#xff1f; 二、MySQL 的功能概覽 三、MySQL 的安裝與啟動 安裝 MySQL 啟動服務 四、Node.js 如何連接 MySQL&#xff1f; 使用 mysql2 模塊&#xff08;推薦&#xff09; 建立連接 五、創建數據表和插入數據&#xff08;SQL 初始化&#xff09…

解鎖高效敏捷:2025年Scrum項目管理工具的核心應用解析

一、為什么Scrum團隊需要專業項目管理工具&#xff1f;在敏捷開發實踐中&#xff0c;Scrum框架雖然提供了基礎的工作流程&#xff0c;但缺乏對任務細粒度管理的支持。傳統白板或簡單看板工具往往無法滿足現代敏捷團隊的需求&#xff0c;導致&#xff1a;沖刺規劃混亂&#xff1…

途游大數據面試題及參考答案

Java 的反射機制是什么?主要應用在哪些場景? Java的反射機制是指程序在運行時,能夠獲取自身類的信息(如類名、屬性、方法、構造器等),并動態操作這些信息的能力。正常情況下,Java代碼編譯時類型已確定,而反射打破了這種編譯期約束,讓程序在運行時靈活操作類和對象。 …

貪心+矩陣算法

貪心算法貪心的本質是&#xff1a;選擇每一階段的局部最優&#xff0c;從而達到全局最優做題的時候&#xff0c;只要想清楚 局部最優 是什么&#xff0c;如果推導出全局最優&#xff0c;其實就夠了。買賣股票的最佳實際思路&#xff1a;如果第i天賣出股票&#xff0c;則最大利潤…

STM32U5 周期性異常復位問題分析

關鍵字&#xff1a; Option Bytes, IDWG 1. 問題背景 客戶反饋使用 NUCLEO_STM32U575 進行評估時&#xff0c;發現板子燒錄完程序后&#xff0c;能看到指示程序運行的 LED 燈正常點亮&#xff0c;但是程序跑不起來。仔細觀察 LED 指示燈&#xff0c;并不是常亮而是出現周期性…

RedisBloom使用

安裝RedisBloom模塊&#xff0c;從git獲取對應的原碼&#xff0c;make生成.so文件&#xff0c;掛載.so文件&#xff0c;啟動redis docker run --name test-redis -v /iothub/test-redis/data:/data -v /iothub/test-redis/modules:/modules -p 6378:6379 -d redis:4.0.10 redis…

ADC、Flash、SPI、watchdog

ADCADC(Analog-to-Digital Converter), 即模擬信號 - 數字信號轉換器在STM32F103C8T6中, 同樣具有ADC功能.以我們的芯片為例, 也存在2個片上外設ADC, 即ADC1和ADC2, 這兩個ADC片上外設都掛載在APB2總線上.我們的ADC片上外設, 是一種具有12位逐次逼近型ADC,ADC轉換的本質是不斷的…

冷庫設備遠程監控物聯網+省電節能解決方案

隨著生鮮電商、醫藥冷鏈、跨境物流等行業的爆發式增長&#xff0c;我國冷庫容量激增&#xff0c;但傳統冷庫管理模式正面臨嚴峻挑戰。據統計&#xff0c;國內冷鏈運輸損耗率高達12%-15%&#xff0c;其中因溫度失控導致的貨損占比超60%。在某醫藥企業冷庫事故中&#xff0c;因制…

如何開發一個運行在windows系統服務器上的服務

第一步&#xff1a;vs2022創建一個windows服務項目第二步&#xff1a;從工具箱拖拽出一個timer第三步&#xff1a;按下圖所示進入&#xff0c;開始編輯業務邏輯下面給個例子using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; …