知識(shí)點(diǎn)13:雙鏈接表(doubly-linked lists)

So if you find yourself in a situation where you're trying to delete single elements from the list or it's going to be required that you'll be deleting single elements from the list, you might want to consider using a doubly-linked list instead of a singly-linked list.

Because doubly-linked lists allow you to move both forwards and backwards through the list instead of just forward through the list -- just by adding one extra element to our structure definition for the doubly-linked list node.

you might decide it's not worth the trade off to have to spend the extra bytes of memory required for a doubly-linked list if you're not going to be deleting single elements. But they're also cool for other things too.

So as I said, we just have to add one single field to our structure definition -- this notion of a Previous pointer.

So with a singly-linked list, we have the value and the Next pointer, so the doubly-linked list just has a way to move backwards as well.


Now in the singly-linked list video, we talked about these are five of the main things you need to be able to do to work with linked lists. And for most of these, the fact that it's a doubly-linked list isn't really a big jump.

We can still search through by just moving forward from start to end.

We can still create a node out of thin air, pretty much the same way.

We can delete lists pretty much the same way too.

The only things that are subtly different, really, are inserting new nodes into the list, and we'll finally talk about deleting a single element from the list as well.

Again, pretty much the other three, we're not going to talk about them right now because they're just very minor tweaks on the ideas discussed in the singly-linked list video.


So let's insert a new node into a doubly-linked list. We talked about doing this for singly-linked lists as well, but there's a couple of extra catches with doubly-linked lists. We're passing in the head of the list here and some arbitrary value, and we want to get the new head of the list out of this function. That's why it returns a dllnode star.

So what are the steps?

They are, again, very similar to singly-linked lists with one extra addition.

We want to allocates space for a new node and check to make sure it's valid. We want to fill that node up with whatever information we want to put in it. The last thing we need to do-- the extra thing we need to do, rather -- is to fix the Previous pointer of the old head of the list.

Remember that because of doubly-linked lists, we can move forward and backwards-- which means that each node actually points to two other nodes instead of just one.

And so we need to fix the old head of the list to point backward to the new head of the linked list, which was something we didn't have to do before. And as before, we just return a pointer to the new head of the list.

So here's a list. We want to insert 12 into this list. Notice that the diagram is slightly different.

Each node contains three fields -- data, and a Next pointer in red, and a Previous pointer in blue.

Nothing comes before the 15 node, so its Previous pointer is null. It's the beginning of the list. There's nothing before it. And nothing comes after the 10 node, and so it's Next pointer is null as well.

So let's add 12 to this list. We need malloc space for the node. We put 12 inside of it.

And then again, we need to be really careful not to break the chain. We want to rearrange the pointers in the correct order.

And sometimes that might mean -- as we'll see particularly with delete --that we do have some redundant pointers, but that's OK.

So what do we want to do first? I would recommend the things you should probably do are to fill the pointers of the 12 node before you touch anybody else. So what is 12 going to point to next? 15.

What comes before 12?

Nothing.

Now we've filled the extra information in 12 so it has Previous, Next, and value.

Now we can have 15-- this extra step we were talking about -- we can have 15 point back to 12.

And now we can move the head of the linked list to also be 12.

So it's pretty similar to what we were doing with singly-linked lists, except for the extra step of connecting the old head of the list back to the new head of the list.


Now let's finally delete a node from a linked list. So let's say we have some other function that is finding a node we want to delete and has given us a pointer to exactly the node that we want to delete. We don't even need-- say the head is still globally declared. We don't need head here. All this function is doing is we've found a pointer to exactly the node we want to get rid of. Let's get rid of it. It's a lot easier with doubly-linked lists.

First-- it's actually just a couple things. We just need to fix the surrounding nodes' pointers so that they skip over the node we want to delete. And then we can delete that node.

So again, we're just going through here. We have apparently decided that we want to delete the node X. And again, what I'm doing here -- by the way -- is a general case for a node that is in the middle.

There are a couple of extra caveats that you need to consider when you're deleting the very beginning of the list or the very end of the list. There's a couple of special corner cases to deal with there.

So this works for deleting any node in the middle of the list-- one that has a legitimate pointer forward and a legitimate pointer backward, legitimate Previous and Next pointer.

Again, if you're working with the ends, you need to handle those slightly differently, and we're not going to talk about that now. But you can probably figure out what needs to be done just by watching this video.

So we've isolated X. X is the node we want to delete from the list.

What do we do?

First, we need to rearrange the outside pointers.

We need to rearrange 9's next to skip over 13 and point to 10-- which is what we've just done. And we also need to rearrange 10's Previous to point to 9 instead of pointing to 13.

Now notice, if you follow the arrows, we can drop 13 without actually losing any information.

We've kept the integrity of the list, moving both forward and backward.

And then we can just sort of clean it up a little bit by pulling the list together.

So we rearranged the pointers on either side. And then we freed X the node that contained 13, and we didn't break the chain. So we did good.


Final note here on linked lists.

So there's trade offs. There's a bit of a pro and con element here.

And doubly-linked lists are not the last kind of data structure combination that we'll talk about, taking all the basic building blocks of C an putting together.

Because in fact, we can even do better than this to create a data structure that you might be able to search through in constant time too.

The End
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末但绕,一起剝皮案震驚了整個(gè)濱河市尖飞,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌启泣,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件示辈,死亡現(xiàn)場(chǎng)離奇詭異寥茫,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)矾麻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門纱耻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人险耀,你說(shuō)我怎么就攤上這事弄喘。” “怎么了甩牺?”我有些...
    開封第一講書人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵蘑志,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我贬派,道長(zhǎng)急但,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任搞乏,我火速辦了婚禮波桩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘请敦。我一直安慰自己突委,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開白布冬三。 她就那樣靜靜地躺著匀油,像睡著了一般。 火紅的嫁衣襯著肌膚如雪勾笆。 梳的紋絲不亂的頭發(fā)上敌蚜,一...
    開封第一講書人閱讀 51,258評(píng)論 1 300
  • 那天,我揣著相機(jī)與錄音窝爪,去河邊找鬼弛车。 笑死齐媒,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的纷跛。 我是一名探鬼主播喻括,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼贫奠!你這毒婦竟也來(lái)了唬血?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤唤崭,失蹤者是張志新(化名)和其女友劉穎拷恨,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谢肾,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡腕侄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了芦疏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片冕杠。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖酸茴,靈堂內(nèi)的尸體忽然破棺而出拌汇,到底是詐尸還是另有隱情,我是刑警寧澤弊决,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站魁淳,受9級(jí)特大地震影響飘诗,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜界逛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一昆稿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧息拜,春花似錦溉潭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至赞别,卻和暖如春畏陕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背仿滔。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工惠毁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留犹芹,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓鞠绰,卻偏偏與公主長(zhǎng)得像腰埂,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蜈膨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容