劉火良 FreeRTOS內核實現與應用之1——列表學習

重要數據

節點的命名都以_ITEM后綴進行,鏈表取消了后綴,直接LIST

普通的節點數據類型

/* 節點結構體定義 */

struct xLIST_ITEM

{

? ? TickType_t xItemValue; ? ? ? ? ? ? /* 輔助值,用于幫助節點做順序排列 */ ? ? ? ? ? ?

? ? struct xLIST_ITEM * ?pxNext; ? ? ? /* 指向鏈表下一個節點 */ ? ? ?

? ? struct xLIST_ITEM * ?pxPrevious; ? /* 指向鏈表前一個節點 */ ?

? ? void * pvOwner; ? ? ? ? ? ? ? ? ? ?/* 指向擁有該節點的內核對象,通常是TCB */

? ? void * ?pvContainer; ? ? ? ? ? ? ? /* 指向該節點所在的鏈表 */

};

typedef struct xLIST_ITEM ListItem_t; ?/* 節點數據類型重定義 */



迷你節點數據類型

/* mini節點結構體定義,作為雙向鏈表的結尾

? ?因為雙向鏈表是首尾相連的,頭即是尾,尾即是頭 */

struct xMINI_LIST_ITEM

{

? ? TickType_t xItemValue; ? ? ? ? ? ? ? ? ? ? ?/* 輔助值,用于幫助節點做升序排列 */

? ? struct xLIST_ITEM * ?pxNext; ? ? ? ? ? ? ? ?/* 指向鏈表下一個節點 */

? ? struct xLIST_ITEM * ?pxPrevious; ? ? ? ? ? ?/* 指向鏈表前一個節點 */

};

typedef struct xMINI_LIST_ITEM MiniListItem_t; ?/* 最小節點數據類型重定義 */

鏈表數據類型

/* 鏈表結構體定義 */

typedef struct xLIST

{

? ? UBaseType_t uxNumberOfItems; ? ?/* 鏈表節點計數器 */

? ? ListItem_t * ?pxIndex; ? ? ? ? ?/* 鏈表節點索引指針 */

? ? MiniListItem_t xListEnd; ? ? ? ?/* 鏈表最后一個節點 */

} List_t;

函數

1. 鏈表插入函數? vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )

升序插入函數

新的節點項插入后,需要解開原來的鏈接,建立新的鏈接:

語句1:向后看:新的節點項指向插入出(后面的)

pxNewListItem->pxNext = pxIterator->pxNext; // 插入,建立新的鏈接;

語句2:向前看:插入出(后面的)指向新的節點項

pxNewListItem->pxNext->pxPrevious = pxNewListItem; // 插入,建立新的鏈接;

語句3:向前看:新的節點項的前面為插入出(前面的)

pxNewListItem->pxPrevious = pxIterator; // 插入,建立新的鏈接;

語句4:向后看:插入出(前面的)指向新的節點項

pxIterator->pxNext = pxNewListItem;// 插入,建立新的鏈接;

/* 將節點按照升序排列插入到鏈表 */
void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem )
{
?? ?ListItem_t *pxIterator;
?? ?
?? ?/* 獲取節點的排序輔助值 */
?? ?const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;

?? ?/* 尋找節點要插入的位置 */
?? ?if( xValueOfInsertion == portMAX_DELAY )
?? ?{
?? ??? ?pxIterator = pxList->xListEnd.pxPrevious;
?? ?}
?? ?else
?? ?{
?? ??? ?for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd );
?? ??? ? ? ? pxIterator->pxNext->xItemValue <= xValueOfInsertion;?
?? ??? ??? ? pxIterator = pxIterator->pxNext )
?? ??? ?{
?? ??? ??? ?/* 沒有事情可做,不斷迭代只為了找到節點要插入的位置 */?? ??? ??? ?
?? ??? ?}
?? ?}

?? ?pxNewListItem->pxNext = pxIterator->pxNext;
?? ?pxNewListItem->pxNext->pxPrevious = pxNewListItem;
?? ?pxNewListItem->pxPrevious = pxIterator;
?? ?pxIterator->pxNext = pxNewListItem;

?? ?/* 記住該節點所在的鏈表 */
?? ?pxNewListItem->pvContainer = ( void * ) pxList;

?? ?/* 鏈表節點計數器++ */
?? ?( pxList->uxNumberOfItems )++;
}

2. 鏈表尾部插入函數? void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )

根節點既是頭部也是尾部,當Item4插入,調用vListInsertEnd,插入如圖所示位置,尾部插入

/* 將節點插入到鏈表的尾部 */

void vListInsertEnd( List_t * const pxList, ListItem_t * const pxNewListItem )

{

? ? ListItem_t * const pxIndex = pxList->pxIndex;

? ? pxNewListItem->pxNext = pxIndex;

? ? pxNewListItem->pxPrevious = pxIndex->pxPrevious;

? ? pxIndex->pxPrevious->pxNext = pxNewListItem;

? ? pxIndex->pxPrevious = pxNewListItem;

? ? /* 記住該節點所在的鏈表 */

? ? pxNewListItem->pvContainer = ( void * ) pxList;

? ? /* 鏈表節點計數器++ */

? ? ( pxList->uxNumberOfItems )++;

}

3. 鏈表刪除節點函數?

刪除節點,解開原來的鏈接,建立新的鏈接:

函數中為何會修改:pxList->pxIndex = pxItemToRemove->pxPrevious,

上面的建立函數一直沒有修改鏈表中根節點的索引值的,索引值一直是指向根節點內部的xListEnd(根節點初始化的時候設置的。),既然建立的時候沒有改變,為何刪除的時候改變?

我的理解是保護用的,其實用處不大

/* 將節點從鏈表中刪除 */

UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )

{

? ? /* 獲取節點所在的鏈表 */

? ? List_t * const pxList = ( List_t * ) pxItemToRemove->pvContainer;

? ? pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;

? ? pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;

? ? /* Make sure the index is left pointing to a valid item. */

? ? if( pxList->pxIndex == pxItemToRemove )

? ? {

? ? ? ? pxList->pxIndex = pxItemToRemove->pxPrevious;

? ? }

? ? /* 初始化該節點所在的鏈表為空,表示節點還沒有插入任何鏈表 */

? ? pxItemToRemove->pvContainer = NULL;

? ?

? ? /* 鏈表節點計數器-- */

? ? ( pxList->uxNumberOfItems )--;

? ? /* 返回鏈表中剩余節點的個數 */

? ? return pxList->uxNumberOfItems;

}

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

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

相關文章

Uniapp項目運行到微信小程序、H5、APP等多個平臺教程

摘要&#xff1a;Uniapp作為一款基于Vue.js的跨平臺開發框架&#xff0c;支持“一次開發&#xff0c;多端部署”。本文將手把手教你如何將Uniapp項目運行到微信小程序、H5、APP等多個平臺&#xff0c;并解析常見問題。 一、環境準備 在開始前&#xff0c;請確保已安裝以下工具…

100天精通Python(爬蟲篇)——第115天:爬蟲在線小工具_Curl轉python爬蟲代碼工具(快速構建初始爬蟲代碼)

文章目錄 一、curl是什么&#xff1f;二、爬蟲在線小工具&#xff08;牛逼puls&#xff09;三、實戰操作 一、curl是什么&#xff1f; 基本概念&#xff1a;curl 支持多種協議&#xff0c;如 HTTP、HTTPS、FTP、SFTP 等&#xff0c;可用于從服務器獲取數據或向服務器發送數據&a…

[內網安全] Windows 域認證 — Kerberos 協議認證

&#x1f31f;想系統化學習內網滲透&#xff1f;看看這個&#xff1a;[內網安全] 內網滲透 - 學習手冊-CSDN博客 0x01&#xff1a;Kerberos 協議簡介 Kerberos 是一種網絡認證協議&#xff0c;其設計目標是通過密鑰系統為客戶機 / 服務器應用程序提供強大的認證服務。該認證過…

PyTorch中的損失函數:F.nll_loss 與 nn.CrossEntropyLoss

文章目錄 背景介紹F.nll_loss什么是負對數似然損失&#xff1f;應用場景 nn.CrossEntropyLoss簡化工作流程內部機制 區別與聯系 背景介紹 無論是圖像分類、文本分類還是其他類型的分類任務&#xff0c;交叉熵損失&#xff08;Cross Entropy Loss&#xff09;都是最常用的一種損…

案例1_3:流水燈

文章目錄 文章介紹原理圖&#xff08;同案例1_2&#xff09;代碼效果圖 文章介紹 原理圖&#xff08;同案例1_2&#xff09; 代碼 #include <reg51.h> // 包含頭文件void delay(unsigned int time) {unsigned int i, j;for (i 0; i < time; i)for (j 0; j < 1…

基于物聯網技術的電動車防盜系統設計(論文+源碼)

1總體設計 本課題為基于物聯網技術的電動車防盜系統&#xff0c;在此將整個系統架構設計如圖2.1所示&#xff0c;其采用STM32F103單片機為控制器&#xff0c;通過NEO-6M實現GPS定位功能&#xff0c;通過紅外傳感器檢測電瓶是否離開位&#xff0c;通過Air202 NBIOT模塊將當前的數…

學習知識的心理和方法雜記-02

本文簡單記錄下我個人對大腦學習模式的認識。 人腦的基本能力是什么&#xff1f; 接收輸入的能力。語言和聲音 視覺圖像 觸覺 嗅覺 味覺等。 存儲能力。人腦存儲能力背后的物理化學結構我們人類目前還無法完全認知&#xff0c;但是存儲的目標物一定是人可以通過五官獲得的形…

國產化替換案例:CACTER郵件網關為Groupwise系統加固郵件安全防線

電子郵件作為企業信息流轉的命脈&#xff0c;承載著商業機密與客戶數據。然而&#xff0c;網絡攻擊手段日益復雜&#xff0c;釣魚郵件等威脅正快速侵蝕企業安全防線。據《2024年第四季度企業郵箱安全性研究報告》顯示&#xff0c;2024年Q4企業郵箱用戶遭遇的釣魚郵件數量激增至…

3.使用ElementUI搭建側邊欄及頂部欄

1. 安裝ElementUI ElementUI是基于 Vue 2.0 的桌面端組件庫。使用之前&#xff0c;需要在項目文件夾中安裝ElementUI&#xff0c;在終端中輸入以下命令&#xff0c;進行安裝。 npm i element-ui -S并在main.js中引入ElementUI 2. 使用elmentUI組件進行頁面布局 2.1 清空原…

C++并發以及多線程的秘密

1.基礎概念 并發&#xff08;Concurrency&#xff09; 并發是指在同一時間段內&#xff0c;多個任務看起來像是同時執行的。并發并不一定意味著真正的同時執行&#xff0c;它可以是通過時間片輪轉等方式在多個任務之間快速切換&#xff0c;讓用戶感覺多個任務在同時進行。并發…

從零開始實現大語言模型(十四):高階訓練技巧

1. 前言 預訓練大語言模型的流程與訓練普通神經深度網絡模型本質上并沒有任何不同。可以使用深度學習實踐中已經被證明非常有效的高階訓練技巧&#xff0c;優化大語言模型預訓練流程&#xff0c;使大語言模型預訓練效率更高&#xff0c;訓練過程更穩定。 本文介紹深度學習領域…

利用EasyCVR平臺打造化工園區視頻+AI智能化監控管理系統

化工園區作為化工產業的重要聚集地&#xff0c;其安全問題一直是社會關注的焦點。傳統的人工監控方式效率低下且容易出現疏漏&#xff0c;已經難以滿足日益增長的安全管理需求。 基于EasyCVR視頻匯聚平臺構建的化工園區視頻AI智能化應用方案&#xff0c;能夠有效解決這些問題&…

GB28181視頻監控流媒體平臺LiveGBS如何自定義收流端口區間以便減少收流端口數或解決端口沖突問題

LiveGBS GB28181流媒體服務在接收視頻的時候默認是使用30000-30249&#xff0c; webrtc流播放端口區間默認是UDP的30250-30500區間。有些網絡環境不方便開放這么大的端口區間&#xff0c;下面介紹下如何修改配置這個區間。 從頁面上修改這個區間&#xff0c;端口區間盡量設置大…

Qt:事件

目錄 處理事件 鼠標事件 鍵盤事件 定時器事件 窗口事件 雖然 Qt 是跨平臺的 C 開發框架&#xff0c;Qt 的很多能力其實是操作系統提供的 只不過 Qt 封裝了系統的 API 事件 前面學習過信號槽&#xff1a; 用戶進行的各種操作&#xff0c;就可能會產生出信號&#xff0c;可以…

責任鏈模式:優雅處理復雜流程的設計藝術

引言 在軟件設計中&#xff0c;我們經常會遇到需要按特定順序處理請求的場景。例如&#xff0c;一個訂單處理系統可能需要經過驗證、付款、物流安排和客戶通知等多個步驟。如果我們將這些步驟硬編碼在一個方法中&#xff0c;代碼將變得臃腫且難以維護。這時&#xff0c;責任鏈…

【STM32】玩轉IIC之驅動MPU6050及姿態解算

目錄 前言 一.MPU6050模塊介紹 1.1MPU6050簡介 1.2 MPU6050的引腳定義 1.3MPU6050寄存器解析 二.MPU6050驅動開發 2.1 配置寄存器 2.2對MPU6050寄存器進行讀寫 2.2.1 寫入寄存器 2.2.2讀取寄存器 2.3 初始化MPU6050 2.3.1 設置工作模式 2.3.2 配置采樣率 2.3.3 啟…

【ThreeJS Basics 09】Debug

文章目錄 簡介從 dat.GUI 到 lil-gui例子安裝 lil-gui 并實例化不同類型的調整改變位置針對非屬性的調整復選框顏色 功能/按鈕調整幾何形狀文件夾調整 GUI寬度標題關閉文件夾隱藏按鍵切換 結論 簡介 每一個創意項目的一個基本方面是能夠輕松調整。開發人員和參與項目的其他參與…

【Pandas】pandas Series explode

Pandas2.2 Series Computations descriptive stats 方法描述Series.argsort([axis, kind, order, stable])用于返回 Series 中元素排序后的索引位置的方法Series.argmin([axis, skipna])用于返回 Series 中最小值索引位置的方法Series.argmax([axis, skipna])用于返回 Series…

電腦網絡出現問題!簡單的幾種方法解除電腦飛行模式

在某些情況下&#xff0c;您可能需要關閉電腦上的飛行模式以便重新連接到 Wi-Fi、藍牙或其他無線網絡。本教程中簡鹿辦公將指導您如何在 Windows 和 macO S操作系統上解除飛行模式。 一、Windows 系統下解除飛行模式 通過快捷操作中心 步驟一&#xff1a;點擊屏幕右下角的通知…

nature genetics | SCENT:單細胞多模態數據揭示組織特異性增強子基因圖譜,并可識別致病等位基因

–https://doi.org/10.1038/s41588-024-01682-1 Tissue-specific enhancer–gene maps from multimodal single-cell data identify causal disease alleles 研究團隊和單位 Alkes L. Price–Broad Institute of MIT and Harvard Soumya Raychaudhuri–Harvard Medical S…