主頁 > 軟體設計 > 【每天學一點系列~】還在困惑資料結構(尤其是鏈表)里指標的看這里!!!

【每天學一點系列~】還在困惑資料結構(尤其是鏈表)里指標的看這里!!!

2021-08-11 07:52:33 軟體設計

一定要搞定指標啊!!!

  • Part I、說在前面兒
  • Part II、指標它是個啥?
    • 1、地址
    • 2、指標的指向作用
    • 2、地址與資料
    • 3、解參考
    • 4、二級指標
    • 5、傳址呼叫
  • Part III、資料結構里的指標
    • 1、不帶頭單鏈表
    • 2、帶頭鏈表
  • Part IV、總結一下(都是精華啊)

Part I、說在前面兒

正在學習資料結構的同學,尤其是正在學習鏈表的同學往往會有這樣的疑問:為什么有的地方傳一級指標,有的地方傳二級指標?為什么帶頭跟不帶頭差別那么大…對于C語言的基礎,尤其是指標的基礎不是那么好的同學,資料結構簡直就是勸退的攔路虎,

說到這里不知道你的DNA是不是動了一下呢?頭又暈了?沒關系,今天我們就來克服指標恐懼癥!

Part II、指標它是個啥?

我們想理清指標,就先從它的本質說起,別劃過,基礎不牢,地動山搖哈,

1、地址

電腦的記憶體可以按照位元組劃分,為了區分這些位元組,我們用十六進制數字給它們進行編號,這些編號就是所謂的地址,
關鍵字提煉:地址對應記憶體上的一個位元組

2、指標的指向作用

指標,就是個箭頭,生活中我們見過路牌,見過指南針,它們都差不多,都是引路者,路牌和指南針都能帶我們回家,而指標的作用,也是告訴我們地址,
在這里插入圖片描述

試問:路牌沒了,路還在嗎?
答案是不是很明顯?當然存在!
所以這里就要明白第一個點:指標只能告訴我們地址,指引我們找到一塊記憶體,但是當這個指標被我們銷毀,或者說,讓它指向別的地方了,這塊記憶體上的東西是不是還在?是!

2、地址與資料

在這里插入圖片描述
我們知道,指標里存盤的是一塊地址,那這塊地址上存盤的內容是啥呢?
舉個例子,假設我們有一個int型別的變數a,里面存盤著資料1,十六進制表示就是0x00000001,那么他在記憶體中的存盤形式就是這樣的:
在這里插入圖片描述
a占四個位元組,而一個變數只對應了一個指標,這個指標保存的是第一個位元組,
可以看到:指標p保存的是地址,而地址對應位元組上的內容,

3、解參考

一個東西的存在讓指標有了新的能力——解參考符號*
如果說指標是路牌,那解參考就是一輛車,有了指向,有了車,我們就可以直達那塊“地址”!
既然到了這塊地址,那么我們能做的就多了:利用這塊地址上的東西,或者改變這塊地址上的東西,
提煉:指標存盤的是地址,對指標解參考其實就是對地址解參考,地址對應記憶體,地址上的東西也就是記憶體上存盤的資料,解參考的操作就是賦予我們訪問和改變這些資料的能力!

4、二級指標

認識了解參考,我們就能學習下一個東西了:二級指標,二級指標又是個啥呢?
首先我們需要清楚一點:指標是不是資料?
指標當然是資料!這個資料就是地址,而地址的本質其實是十六進制的資料,這些資料存放在一種叫指標的變數當中,
既然要存盤資料,那么指標是不是也占記憶體?既然是記憶體,那么它是不是也有一個地址?這個地址就可以存放在一個二級指標當中,
在這里插入圖片描述
如果我們對二級指標解參考,就可以獲得一級指標上存盤的內容(也是一個地址),然后再解參考,就能獲得一級指標存盤的地址上存盤的資料,(有點繞哦,對應這上面的圖理一下)
ok,繼續!

5、傳址呼叫

這個很重要!!!這個很重要!!!這個很重要!!!
為什么有傳址呼叫這個東西?因為形參與實參之間幾乎沒有任何聯系,實參對應一個地址,形參對應另外一個地址,當我們改變形參,只是把它的地址上存的資料改了,但是實參對應的地址上的東西還是沒變,

那如果我們傳的是實參的地址呢?此時形參就是一級指標,這個指標存盤的是實參的地址,對它進行解參考,就能訪問或修改實參的地址上存盤的資料了!
典型的例子就是交換兩個數的Swap函式,

void Swap(int* x , int*y)
{
	int tmp = *x;
	*x = *y;
	*y = tmp;
}

認識了這些,就讓我們直接進入資料結構的正題,

Part III、資料結構里的指標

1、不帶頭單鏈表

鏈表的節點的定義一上來就會給我們一個下馬威:

typedef struct Node
{
	int data;
	struct Node* next;
}Node;

這里有一個自參考next,它指向的也是一個Node型別的指標,
意思就是說:

一個節點存一個資料,然后又存了一個指標,這個指標的內容是下一個節點的地址,換句話說,這個指標指向下一個節點,因此鏈表才能真正意義上“鏈接”起來,

在這里插入圖片描述
我們定義了一個pList指標專門指向鏈表的第一個節點,也就是頭(head),因為它指向一個節點,所以它是一個Node型別的指標,即Node*,

由于一開始鏈表沒有元素,自然也沒有頭結點,所以我們令pList = NULL,讓它指向空,
緊接著我們就會寫頭插頭刪和尾插尾刪函式,于是,詭異的二級指標就來了,

我們不妨看一個頭插函式的原型:

void SListPushFront(Node** ppList, int x);

而我們呼叫它時就要這樣:

void SListPushFront(&pList,0);

為什么要取地址呢?換句話說,為什么要傳址呢?

原因很簡單:因為我們的操作會改變這里的pList,(注意改變二字)

頭插意味著鏈表的頭不再是當前pList指向的那個節點,而是另一個新插入的newnode,我們讓newnode的next指向當前的pList,然后再讓pList指向newnode,
但是,如果傳的是pList而不是&pList,那么由于傳值呼叫,形參的改變不影響實參——盡管你讓形參指向了newnode,但是pList存盤的還是之前的那個節點的地址,然后出現這樣的窘境:
在這里插入圖片描述
pList指向鏈表的第二個結點而非第一個,
以后我們遍歷鏈表都是從pList指向的位置開始的,但是pList由于是傳值,它永遠都指向同一塊地方,不會改變,因此我們能遍歷到的,也永遠只有從當前位置開始,到NULL結束,

那么為什么尾插尾刪這些函式也要傳二級指標呢?設想:如果鏈表為空,尾插的那個元素就是新的頭結點,是不是就會改變pList?如果鏈表只有一個元素,此時它就是鏈表的頭,那尾刪是不是也會改變pList?

總而言之,對于不帶頭的鏈表來說,可能改變鏈表的頭的函式,都要用二級指標,只有傳二級指標,也就是pList的地址,才能在函式的內部改變pList,讓pList指向新的頭!

2、帶頭鏈表

同學們好不容易弄清鏈表需要傳二級指標,突然又遇到了一種不用傳二級指標的鏈表,啥情況??不讓人活了?別慌,讓我們一起看看,

帶頭的鏈表與不帶頭的鏈表的區別就是:不帶頭的鏈表用一個pList指標來維護,而帶頭的鏈表用一個哨兵位來維護,什么是哨兵位?其實哨兵位也是一個結點,但是它并不存盤任何的有效資料,

與不帶頭的單鏈表相比,帶哨兵位的好處多多,這個在各位刷到鏈表相關的演算法題之后就能察覺到,它能帶來很多代碼上的優化,可以少考慮很多邊界情況,
不過當前, 它的最大的優點就是:不用傳二級指標,為啥?

ListNode* list = ListCreate();

我們先創建一個哨兵位list,
在這里插入圖片描述
可以看到,哨兵位是頭結點前的一個節點,頭結點的地址就是哨兵位的next指標存盤的內容,
當我們進行傳參時,直接把list這個指標傳給形參,形參作為實參的臨時拷貝,里面存盤的內容就跟list指標完全一樣,也就是說:
形參里也有一個指標,這個指標存盤的內容跟哨兵位的next指標存盤的內容一樣,都是頭結點的地址!有了這個地址,我們就可以修改這個地址上的內容,也就是說:修改頭結點,

看到這里,我們應該明白:1、形參和實參的next指標肯定是兩個不同的變數,但是它們存盤的內容是相同的,都是頭結點的地址,2、只要有地址,我們就能修改地址上的內容,無所謂存盤這個地址的指標是誰,

剛剛不帶哨兵位的情況下,pList需要傳二級指標,因為它需要始終保持指向頭指標,而這里的list永遠指向的是哨兵位,head的改變只會影響list的next,當我們直接傳list時,形參部分接收的就是list的內容(包括那個指向頭結點的指標),通過它我們就可以直接訪問list里的next,從而改變它,

Part IV、總結一下(都是精華啊)

想玩轉指標,最重要的是什么?是要知道:
1、指標存盤的是地址
2、地址對應記憶體
3、只要我們能得到這個地址,就能通過解參考訪問或修改對應記憶體上的資料
4、如果傳址,形參接收實參的地址,對形參解參考得到的就是實參這個物體,
5、如果是傳值,形參會復刻實參的內容,如果內容中存在指標,那么我們同樣可以通過這個指標修改對應記憶體上的資料,
6、如果我們想通過形參達到修改實參的目的,必須要傳址!

最重要的一點:對于實參是指標的情況,如果我們僅僅想操作它存盤的地址上的內容,那么傳值就足夠了,如果還想額外地改變實參,讓實參存盤別的地址,那么就需要傳地址了!

不知道讀者聽懂了嘛,有任何問題可以在評論區反饋給我哦
關注筆者,一起學習,一起進步!

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/292998.html

標籤:其他

上一篇:使用 GitLab + Jenkins 實作持續集成(CI)環境

下一篇:一文帶你搞定二分(真的詳細,建議收藏)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more