線性數據結構:單向鏈表

放棄眼高手低,你真正投入學習,會因為找到一個新方法產生成就感,學習不僅是片面的記單詞、學高數......只要是提升自己的過程,探索到了未知,就是學習。

目錄

? ? ? ? ? ? ? ? ??一.鏈表的理解

? ? ? ? ?二.鏈表的分類(重點理解)

三.無頭單向非循環鏈表

? ? ? ? ? ? ? ? ? ??三.1 節點結構以及理解?

? ? ? ? ? ?三.2遍歷鏈表

??三.3尾插

??三.4增加節點

? 三.5尾刪

? 三.6頭刪

??三.7頭插

? 三.8查找數據

??三.8插在目標節點前面

??三.9插在目標節點后面

??三.10刪除目標節點


在上篇我們學習了順序表,它是在計算機內存中以數組形式保存的線性表,特點是通過一組地址連續的存儲的單元依次存儲線性表中的各個元素,既然地址是連續的,它存在以下幾個問題:

1:在中間/頭部插入刪除,需要對整個空間地址、內容進行移動,比較麻煩

2:如果空間不夠用,那么就需要擴容,這個過程需要拷貝原空間數據,釋放舊空間,消耗較大

3:空間浪費問題,當你已經擴容好了一片空間,但是很多用不完或者又不夠用,需要重新對空間問題進行解決

綜合起來,我們需要更加高效的線性存儲結構:鏈表

一.鏈表的理解

定義:鏈表是一種線性結構,由一系列節點組成,鏈表存在頭(頭節點)和尾(尾節點),節點之間通過指針關聯,每一個數據元素都是獨立存儲的(地址不連續)。鏈表通過指針鏈接次序實現數據元素的邏輯順序,每個節點包含兩個組成部分:數據域與指針。數據域用來存儲數據,指針負責指向下一個節點。鏈表的起點為頭節點,尾節點則是空指針(NULL),用來表示鏈表的結束。

抽象圖示:

特點:?1:動態性。靈活刪除或者插入節點

? ? ? ? ? ? 2:內存利用率高。充分利用空間,實現動態內存管理

? ? ? ? ? ? 3:插入與刪除操作效率高。順序表的刪除插入時間復雜度為O(N),那么鏈表的對應時? ? ? ? ? ? ? ? ? ?間復雜度則達到了O(1),可以在很短的時間內完成插入刪除操作

? ? ? ? ? ? 4:查詢效率低。我們知道鏈表從頭到尾,需要遍歷整個鏈表才能找到目標節點,它的查? ? ? ? ? ? ? ? ? ? ? 找時間復雜度則為O(N)

二.鏈表的分類(重點理解)

鏈表主要可以分為以下3大類:

單向鏈表:單向鏈表中的每一個節點只包含一個指針,指向下一個節點,數據元素的邏輯順序通過鏈表中的指針鏈接次序實現

雙向鏈表:雙向鏈表中的每個節點包含2個指針,分別指向前一個節點與后一個節點

循環鏈表:循環鏈表的第一個節點和最后一個節點通過指針相連,形成一個環狀結構,循環鏈表可以是單向也可以是雙向的

在這3大類中我們還需要了解幾個概念:頭指針頭節點帶頭節點不帶頭節點

頭指針:本質是一個結構體類型的指針,存儲第一個節點的地址

頭節點:本質是一個節點,有數據域與指針。在單鏈表的第一個節點之前再附加一個節點,稱為? ? ? ? ? ? ? ? ? 頭節點,頭節點的數據域可以不放任何信息,也可以記錄鏈表長度。若鏈表是帶有頭節? ? ? ? ? ? ? ? ? 點的,則頭指針指向頭節點的存儲位置

帶頭節點:與其它節點一樣,有數據域跟指針,可以理解為一個結構體變量,只是頭指針指向頭節點存儲位置,圖示:

不帶頭節點 :我們知道帶頭節點是指針指向頭節點,那么反之,不帶頭節點是頭指針指向第一個節點的存儲位置

那么我們簡單總結:無論是否有頭節點,都存在一個頭指針,頭指針都指向鏈表的一個節點,只是區分頭指針是指向第一個節點還是頭節點,圖示理解:

鏈表會根據:單頭或者不帶頭單向或者雙向循環或者非循環進行組合,一共可以組合出8種

其中只要掌握2種,就可以觸類旁通了,我們先重點來學習以下第一種:

無頭單向非循環鏈表? ? ? ? ?帶頭雙向循環鏈表

三.無頭單向非循環鏈表

上面我們已經了解了無頭跟有頭的區別,那這里我們輕而易舉的可以畫個圖:

?三.1 節點結構以及理解?

我們創建了一個指針next跟數據域,這個數據域的類型就是你要存儲的類型,可自行設置,指針指向下一個節點的地址。

這里解釋一下next指針:?鏈表中的next是指向下一個節點的指針(通常稱為next)。所有節點通過next指針連接起來,使得數據元素可以按照一定的順序排列。在雙向鏈表中還有一個指向前一個節點的指針:prev,這使得雙向鏈表可以從頭到尾或從尾到前遍歷,這里僅僅簡單科普一下!

下面我們看幾個常見寫法,來進行錯誤糾正:

我們先用typedef對結構體類型進行重命名,?命名之前結構體類型是struct Student,命名之后可以簡寫為Student,這樣減少了代碼量,方便閱讀。上圖第一種寫法跟第二種寫法都存在一個問題:在進行重命名的結構體里面,類型必須寫全,這是因為現在是屬于聲明階段,出了這個結構體以后才可以用簡寫的方式。舉個例子:一個方案的發布必須是已經制作好的。這里也一樣,typedef目前在這個結構體只是類似方案制作階段,出了這個結構體之后才可以簡化使用。

三.2遍歷鏈表

在遍歷鏈表時,我們需要讓指針靈活的動起來,而不能直接讓節點里面的指針動起來,不然就出問題了,因此我們需要創建一個指針指向節點中的第一個指針,改變這個指針的指向是不是就達到了動態節點的效果!比如我新創建了一個指針 cur?(在下文我們方便講解,還會用到這個指針),每次通過改變cur的指向來改變當前訪問的節點。這里需要注意cur指針是不會真正動的,只是它的指向地址發生改變。圖示理解如下:

在進行鏈表的增刪查找功能前,我們需要掌握遍歷,代碼參考如下:

我們仔細解釋一下圖中比較重要的地方:

1:為什么不需要判斷指針head的有效性?因為head是頭指針,指向第一個節點,指針是空指針只能說明指向的地址不存在,而指向的地址的空間內容是否存在不相干,就好比通訊錄空間,我只是沒有存儲聯系人進去,但是有這個空間,這個大家可以理解嗎?我再舉個例子:現在有一個水杯(head),我需要去拿水杯喝水(head指向地址的內容),杯子里面有沒有水跟這個水杯存不存在不相關!

2:指針head跟指針cur的關系:head是頭指針,是不可以移動的,而將head指針指向的地址交給cur,通過cur的指向移動,實現對節點內容的管理

??3:對while循環的條件的討論:我們看下面2個圖

我們知道頭指針head將第一個節點的地址傳給curcur是指向下一個節點的地址的,當cur到達最后一個節點時,此時cur的指向還是最后一個節點的地址,而cur->next已經是指向空指針了,就少進入了循環一次。cur是通過cur->next來改變cur的指向的,而cur->next已經指向下一個節點了。這個我們結合2張圖理解(物理圖示與邏輯圖示):

?

?三.3尾插

我們從字面上理解,就是在當前最后一個節點后面再插入新節點!再把新節點與尾節點連接起來,那么我們需要用3個操作:找尾節點? 開辟新節點? 連接節點 (最后會對3個步驟匯總代碼講思路)

先解釋一下為什么要用二級指針?因為涉及空鏈表跟鏈表存在的討論,需要更改地址的問題。

下面我們進行第一個操作,找尾節點。我們已經知道如何遍歷鏈表了!既然指針指向下一個節點的地址,那么當這個指針是空指針的時候,是不是就表示找到尾了!這里需要理解的是,這個指針的指向是NULL,因為我們是需要開辟新節點的,自然要在最后一個節點后面開辟,所以需要讓它指向NULL,如圖理解(tailcur等價):

//找尾節點
void Traversal(Pointdef** head)
{//判斷鏈表是不是空鏈表if(*head==NULL){//空鏈表的話新節點作為第一個節點*head=newspointer;}else{//托付head的指向給cur指針Pointdef* cur = *head;//找尾while (cur){//改變 cur 指針的指向cur = cur->next;}//此時cur指向NULL,也就是尾節點的后面}
}

下面我們進行第二個操作:開辟新節點。新節點的創建不能直接使用原節點的類型去創建,因為這樣創建的新節點只是臨時變量,為什么呢?因為我們是在函數里面創建的,當函數調用完,里面的變量就全部銷毀了。因此我們需要用到動態內存開辟,同時初始化指針,至于為什么要初始化,后面會細說,因此用malloc給新節點開辟一塊空間,才能延長新節點生命周期。代碼如下:

Pointdef* Greate()
{Pointdef* news = malloc(sizeof(Pointdef));if (news == NULL){perror("malloc");return NULL;}//理解:news指針指向新節點地址,news->next表示對新節點的指針初始化了news->next = NULL;return news;
}

首先我們看這個函數,它的類型是結構體指針類型,為哈?因為我們用這個函數來開辟新節點,那么開辟的空間類型是節點的結構體類型,我們知道鏈表是用指針連接起來的,那么我們只需要返回一個指針就行了,指針類型肯定是結構體類型,然后用malloc開辟新節點,節點大小是結構體的大小。下面緊接著判斷,判斷新節點是否開辟成功,news->next=NULL,這句話就是告訴我們這是新節點的尾端,因為new->next是指向下一個節點,也就是NULL。大家肯定想知道為哈不初始化這個新節點的數據域呢?單鏈表節點的數據域是否初始化,可以自行設定,未初始化的數據域可能出現一些隨機值。

下面進行第三個操作:連接這2個節點。在連接前需要判斷這個鏈表的頭指針是否存在,否則需要將新節點作為第一個節點,不然會出現嚴重問題。這里涉及空鏈表跟鏈表不存在的區別,如下:

鏈表不存在:如:head==NULL,鏈表都不存在,那么一切操作都無用,因此在使用鏈表時需要檢查鏈表是否存在

空鏈表:鏈表存在,頭指針為空,如:cur==NULL,它的存在與否需要分情況,比如我需要刪除某個節點,那么空鏈表肯定是不行的,而打印、插入節點這些沒什么影響,具體需要根據操作來判斷

//增加新節點
void NewPointer(Pointdef** head)
{assert(head);Pointdef* newpointer = Greate();//如果這個頭指針的指向是空指針,那么鏈表是空的,將這個新節點作為新的節點if (*head == NULL){*head = newpointer;}else{//頭指針指向交給cur,用cur找尾Pointdef* cur = *head;//找尾while (cur->next != NULL){cur = cur->next;}//連接cur->next = newpointer;}
}

總結:上面代碼我們是進行拆分了的,如果看不懂,我們可以用筆一步步記錄,理清思路。尾插的總思路就是:先判斷鏈表是否存在,再用函數新增節點,然后判斷空鏈表,最后找尾進行連接。參考完整代碼:

//增加新節點
Pointdef* Greate()
{Pointdef* news = malloc(sizeof(Pointdef));if (news == NULL){perror("malloc");return NULL;}//理解:news指針指向新節點地址,new->next標識它是將要接入的最后一個節點,相當于初始化了news->next = NULL;return news;
}//找尾+連接
void NewPointer(Pointdef** head)
{//判斷鏈表是否存在assert(head);Pointdef* newpointer = Greate();//如果這個頭指針的指向是空指針,那么鏈表是空的,將這個新節點作為新的節點if (*head == NULL){*head = newpointer;}else{Pointdef* cur = *head;//找尾while (cur->next == NULL){cur = cur->next;}//連接cur->next = newpointer;}
}
三.4增加節點

新增我們在上面的尾插已經使用過了,我們就不再重復說了,每次操作接收函數返回的指針,就可以控制新增節點的地方,新增節點的函數都是通用的,代碼如下:

//增加新節點
Pointdef* Greate()
{Pointdef* news = malloc(sizeof(Pointdef));if (news == NULL){perror("malloc");return NULL;}//理解:news指針指向新節點地址,news->next理解為標識自己是將要接入的最后一個節點,相當于初始化了news->next = NULL;return news;
}
三.5尾刪

顧名思義,就是刪除最后一個節點,那么我們猜測步驟也就只有2步:先找? 再刪

我們需要先遍歷鏈表,然后找到最后一個節點,進行刪除釋放,再把倒數第二個節點的cur->next改為NULL。尾刪需要注意幾種情況,空鏈表跟唯一節點的鏈表,2種情況,跟尾插一樣,可能需要更改頭指針地址,因此需要使用二級指針。找尾節點跟倒數第二個節點一個指針肯定不夠,因此我們需要兩個指針,一個來找尾節點,一個來找倒數第二個節點。我們來看思維圖,理清雙指針的關系:

代碼如下:

//尾刪
void Taildeletion(Pointdef** head)
{//判斷鏈表是否存在assert(head);//判斷是否是空鏈表assert(*head);//判斷一個節點的情況if (((*head)->next) == NULL){//直接釋放free(*head);*head = NULL;}else{//找尾Pointdef* cur = *head;while (cur->next){cur = cur->next;}//找倒數第二個節點Pointdef* tail = *head;while (cur->next){tail = cur;cur = cur->next;}//釋放尾節點free(cur);cur = NULL;//改變倒數第二個的指向tail->next = NULL;}}
三.6頭刪

有了尾刪的基礎,頭刪也一樣需要考慮空鏈表跟鏈表不存在的情況,先改變頭指針指向,然后直接刪就行了,也不需要找頭,是不是很簡單!代碼如下:

//頭刪
void Headdeletion(Pointdef** head)
{//判斷鏈表是否存在assert(head);//判斷是否是空鏈表assert(*head);//創建指針指向頭Pointdef* cur = *head;//改變頭指針指向*head = (*head)->next;//釋放free(cur);cur = NULL;
}
三.7頭插

頭插管他是不是空鏈表!直接搞個節點當頭就行了!那么我們需要先開一個新節點,再改變頭指針指向,代碼如下:

//頭插
void HeadPointer(Pointdef** head)
{//判斷鏈表是否存在assert(head);//新開節點Pointdef* cur = Greate();//改頭指針跟指向cur->next = *head;*head = cur;
}
三.8查找數據

我們只要給某個節點的數據域初始化,那么就可以通過遍歷鏈表來找這個節點的地址,例如我初始化了某個節點的整型數據域為x,那么就直接遍歷就行了!

//查找數據
Pointdef* Find(Pointdef* head , int x)
{Pointdef* cur = head;//查找while (cur){if (cur->data==x){return cur;}else{cur = cur->next;}}//否則沒有找到return NULL;
}
三.8插在目標節點前面

之前,我們學習了尾插與頭插,那么如果在中間插入新節點呢?我們先遍歷鏈表,找到那個節點,然后在它的前面插入新節點即可(自行選擇插入的節點前后,我這里例舉插在目標節點前面)。這里需要注意的是如果目標節點是第一個節點,那么就是頭插,這里需要改變指針指向,不能是形參,因此需要二級指針。根據對應節點的指針找目標節點,這里我假設cur是目標節點代碼如下:

void Middle(Pointdef** head ,Pointdef* cur,int x)
{//注意:cur是目標節點//判斷空鏈表,否則是頭插if (*head==NULL){HeadPointer(head);}else{//先開新節點Pointdef* news = Greate();//找要增加的節點位置Pointdef* pc = *head;while (pc->next!=cur){pc = pc->next;}//此時pc指向cur的前一個節點//連接節點pc->next = news;news->next = cur;}
}

三.9插在目標節點后面

這個跟前面插在節點前面的類似,但是更簡單。借助指針找到目標節點,在連接就行。代碼如下:

//插在節點后面
void Outdle( Pointdef* cur)
{//注意:cur是目標節點assert(cur);//開辟新節點Pointdef* news = Greate();Pointdef* pc = cur->next;//連接cur->next = news;news->next = pc;
}
三.10刪除目標節點

考慮空鏈表跟鏈表不存在兩種情況,然后循環找到目標節點,連接左右節點再刪除即可!

//刪除目標節點
void Omit(Pointdef** head, Pointdef* cur)
{//cur是要刪除的節點指針//判斷鏈表是否存在assert(head);//判斷空鏈表assert(*head);//循環找目標節點Pointdef* pc = *head;while (pc->next = cur){pc = pc->next;}//連接目標節點的左右節點pc->next = cur->next;//先連接再釋放free(cur);cur = NULL;
}

好了,本篇到此結束,大家記得一鍵三連哦!幾天后我會繼續出帶頭雙向循環鏈表的博文!感謝支持!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

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

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

相關文章

基于PyQt5打造的實用工具——PDF文件加圖片水印,可調大小位置,可批量處理!

01 項目簡介 (1)項目背景 隨著PDF文件在信息交流中的廣泛應用,用戶對圖片水印的添加提出了更高要求,既要美觀,又需高效處理批量文件。現有工具難以實現精確調整和快速批量操作,操作繁瑣且效果不理想。本項…

MCU內部ADC模塊誤差如何校準

本文章是筆者整理的備忘筆記。希望在幫助自己溫習避免遺忘的同時,也能幫助其他需要參考的朋友。如有謬誤,歡迎大家進行指正。 一、ADC誤差校準引言 MCU 片內 ADC 模塊的誤差總包括了 5 個靜態參數 (靜態失調,增益誤差,微分非線性…

嵌入式硬件篇---CPUGPUTPU

文章目錄 第一部分:處理器CPU(中央處理器)1.通用性2.核心數3.緩存4.指令集5.功耗和發熱 GPU(圖形處理器)1.并行處理2.核心數量3.內存帶寬4.專門的應用 TPU(張量處理單元)1.為深度學習定制2.低精…

03-機器學習-數據獲取

一、流行機器學習數據集 主流機器學習數據集匯總 數據集名稱描述來源MNIST手寫數字圖像數據集,由美國人口普查局員工書寫。MNIST官網ImageNet包含數百萬張圖像,用于圖像分類和目標檢測。ImageNet官網AudioSet包含YouTube音頻片段,用于聲音分…

doris:STRUCT

STRUCT<field_name:field_type [COMMENT comment_string], ... > 表示由多個 Field 組成的結構體&#xff0c;也可被理解為多個列的集合。 不能作為 Key 使用&#xff0c;目前 STRUCT 僅支持在 Duplicate 模型的表中使用。一個 Struct 中的 Field 的名字和數量固定&…

一次端口監聽正常,tcpdump無法監聽到指定端口報文問題分析

tcpdump命令&#xff1a; sudo tcpdump -i ens2f0 port 6471 -XXnnvvv 下面是各個部分的詳細解釋&#xff1a; 1.tcpdump: 這是用于捕獲和分析網絡數據包的命令行工具。 2.-i ens2f0: 指定監聽的網絡接口。ens2f0 表示本地網卡&#xff09;&#xff0c;即計算機該指定網絡接口捕…

“新月智能武器系統”CIWS,開啟智能武器的新紀元

新月人物傳記&#xff1a;人物傳記之新月篇-CSDN博客 相關文章鏈接&#xff1a;星際戰爭模擬系統&#xff1a;新月的編程之道-CSDN博客 新月智能護甲系統CMIA--未來戰場的守護者-CSDN博客 “新月之智”智能戰術頭盔系統&#xff08;CITHS&#xff09;-CSDN博客 目錄 智能武…

實驗六 項目二 簡易信號發生器的設計與實現 (HEU)

聲明&#xff1a;代碼部分使用了AI工具 實驗六 綜合考核 Quartus 18.0 FPGA 5CSXFC6D6F31C6N 1. 實驗項目 要求利用硬件描述語言Verilog&#xff08;或VHDL&#xff09;、圖形描述方式、IP核&#xff0c;結合數字系統設計方法&#xff0c;在Quartus開發環境下&#xff…

SCRM系統如何提升客戶管理及業務協同的效率與價值

內容概要 在當今商業環境中&#xff0c;SCRM系統&#xff08;社交客戶關系管理系統&#xff09;正逐漸受到越來越多企業的關注和重視。隨著科技的發展&#xff0c;傳統的客戶管理方式已經無法滿足快速變化的市場需求&#xff0c;SCRM系統通過整合客戶數據和社交網絡信息&#…

[免費]微信小程序智能商城系統(uniapp+Springboot后端+vue管理端)【論文+源碼+SQL腳本】

大家好&#xff0c;我是java1234_小鋒老師&#xff0c;看到一個不錯的微信小程序智能商城系統(uniappSpringboot后端vue管理端)&#xff0c;分享下哈。 項目視頻演示 【免費】微信小程序智能商城系統(uniappSpringboot后端vue管理端) Java畢業設計_嗶哩嗶哩_bilibili 項目介紹…

PID算法的數學實現和參數確定方法

目錄 概述 1 算法描述 1.1 PID算法模型 1.2 PID離散化的圖形描述 1.3 PID算法的特點 2 離散化的PID算法 2.1 位置式PID算法 2.2 增量式PID算法 2.3 位置式PID與增量式PID比較 3 控制器參數整定 3.1 PID參數確定方法 3.1.1 湊試法 3.1.2 臨界比例法 3.1.3 經驗法…

《DeepSeek R1:大模型最簡安裝秘籍》

DeepSeek R1&#xff1a;AI 大模型界的新起之秀 在人工智能的璀璨星空中&#xff0c;大模型如繁星般閃耀&#xff0c;而 DeepSeek R1 無疑是其中一顆冉冉升起的新星&#xff0c;自問世以來便吸引了全球的目光&#xff0c;在人工智能領域占據了重要的一席之地。 從性能表現上看…

【論文閱讀】RAG-Reward: Optimizing RAG with Reward Modeling and RLHF

研究背景 研究問題&#xff1a;這篇文章要解決的問題是如何優化檢索增強生成&#xff08;RAG&#xff09;系統&#xff0c;特別是通過獎勵建模和人類反饋強化學習&#xff08;RLHF&#xff09;來提高大型語言模型&#xff08;LLMs&#xff09;在RAG任務中的效果。研究難點&…

【數據結構】(3)包裝類和泛型

一、包裝類 1、什么是包裝類 將基礎類型包裝成的類就是包裝類。由于基礎類型不是繼承 Object 類的類&#xff0c;所以在泛型不能直接支持基礎類型&#xff0c;為了解決這個問題&#xff0c;就需要把基礎類型轉換為對應的包裝類。 基礎類型對應的包裝類 基礎類型包裝類byteByte…

DBUtils中QueryRunner(空參,傳數據源)構造方法的區別及應用場景

關于學習Spring框架時重構DAO層時&#xff0c;遇到的QueryRunner構造方法的問題&#xff0c;回憶MySQL中DBUtils部分 1. 空參構造方法 new QueryRunner() 特點&#xff1a; 不綁定數據源&#xff1a;QueryRunner 實例內部沒有 DataSource&#xff0c;因此無法自動獲取連接。 …

C++11線程

C11提供了線程庫&#xff0c;下面我們來看一下如何使用。 線程的創建 頭文件 要創建一個線程需要包一個線程頭文件:#include <thread> 我們先來看看thread支持的構造方式。 支持默認構造&#xff0c;直接使用thread創建一個空的線程對象。 也支持帶參的構造&#x…

梯度提升用于高效的分類與回歸

人工智能例子匯總:AI常見的算法和例子-CSDN博客 使用 決策樹(Decision Tree) 實現 梯度提升(Gradient Boosting) 主要是模擬 GBDT(Gradient Boosting Decision Trees) 的原理,即: 第一棵樹擬合原始數據計算殘差(負梯度方向)用新的樹去擬合殘差累加所有樹的預測值重…

Golang 并發機制-3:通道(channels)機制詳解

并發編程是一種創建性能優化且響應迅速的軟件的強大方法。Golang&#xff08;也稱為 Go&#xff09;通過通道&#xff08;channels&#xff09;這一特性&#xff0c;能夠可靠且優雅地實現并發通信。本文將揭示通道的概念&#xff0c;解釋其在并發編程中的作用&#xff0c;并提供…

Unity開發游戲使用XLua的基礎

Unity使用Xlua的常用編碼方式&#xff0c;做一下記錄 1、C#調用lua 1、Lua解析器 private LuaEnv env new LuaEnv();//保持它的唯一性void Start(){env.DoString("print(你好lua)");//env.DoString("require(Main)"); 默認在resources文件夾下面//幫助…

筆記:使用ST-LINK燒錄STM32程序怎么樣最方便?

一般板子在插件上&#xff0c; 8腳 3.3V;9腳 CLK;10腳 DIO;4腳GND ST_Link 19腳 3.3V;9腳 CLK;7腳 DIO;20腳 GND 燒錄軟件&#xff1a;ST-LINK Utility&#xff0c;Keil_5; ST_Link 接口針腳定義&#xff1a; 按定義連接ST_Link與電路板&#xff1b; 打開STM32 ST-LINK Uti…