chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

一個(gè)數(shù)據(jù)結(jié)構(gòu)-線段樹

算法與數(shù)據(jù)結(jié)構(gòu) ? 來(lái)源:算法與數(shù)據(jù)結(jié)構(gòu) ? 2020-05-06 11:02 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

一、概念解析

這次來(lái)介紹一個(gè)數(shù)據(jù)結(jié)構(gòu) - 線段樹。

在平時(shí)刷題或是工作中,經(jīng)常會(huì)遇到這么一個(gè)問(wèn)題,“給定一個(gè)數(shù)組,求出數(shù)組某段區(qū)間的一些性質(zhì)”。

比如給定一個(gè)數(shù)組 [5,2,6,1,-4,0,9,2],讓你求出區(qū)間 [1,4] 上所有元素的和,在這個(gè)例子中,答案是 2 + 6 + 1 + (-4) = 5。

你可能會(huì)說(shuō),直接遍歷一遍不就好了嗎?

最簡(jiǎn)單的方式就是直接遍歷一遍區(qū)間,時(shí)間復(fù)雜度也顯而易見 O(n),如果在這個(gè)數(shù)組上頻繁進(jìn)行這個(gè)操作,那么效率相對(duì)來(lái)說(shuō)會(huì)比較低,怎么優(yōu)化呢?

對(duì)于求區(qū)間和的問(wèn)題,前綴和數(shù)組是一個(gè)不錯(cuò)的選擇,構(gòu)建好前綴和數(shù)組后,求一個(gè)區(qū)間和的話只要前后一減就可以了,如果不算構(gòu)建數(shù)組的時(shí)間,那么每次的操作時(shí)間復(fù)雜度就是 O(1)。

這里的問(wèn)題在于前綴和數(shù)組只能解決求區(qū)間和的問(wèn)題,但是其他的區(qū)間問(wèn)題,前綴和數(shù)組并不能很好的解決,比如求某段區(qū)間上的最大值。

因此我們需要一個(gè)數(shù)據(jù)結(jié)構(gòu)能夠幫助我們解決大部分?jǐn)?shù)組的區(qū)間問(wèn)題,而且時(shí)間復(fù)雜度要盡可能的低。

這也就是今天的主題 - 線段樹,首先要說(shuō)明一點(diǎn)的是,線段樹也是二叉樹,只是它的節(jié)點(diǎn)里面含有區(qū)間的信息。

線段樹每個(gè)節(jié)點(diǎn)表示的是一個(gè)區(qū)間,每個(gè)節(jié)點(diǎn)將其表示的區(qū)間一分為二,左邊分到左子樹,右邊分到右子樹,根節(jié)點(diǎn)表示的是整個(gè)區(qū)間(也就是整個(gè)數(shù)組),葉子節(jié)點(diǎn)表示的是一個(gè) index(也就是單個(gè)元素),因?yàn)槊看螌?duì)半分的緣故,線段樹構(gòu)建出來(lái)是平衡的,也就是說(shuō)樹的高度是 O(logn),這里的 n 表示的是數(shù)組中所有的元素,這一點(diǎn)對(duì)于我們后面分析復(fù)雜度很重要。

線段樹有三個(gè)基本的操作,分別是構(gòu)建線段樹(build)、區(qū)間查找(query)、還有就是修改(modify),假設(shè)我們現(xiàn)在需要解決的問(wèn)題是 “求區(qū)間上的最大值”,例子還是之前的例子,一起來(lái)看看怎么實(shí)現(xiàn)這些操作。

對(duì)于構(gòu)建操作來(lái)說(shuō),相對(duì)簡(jiǎn)單,你只需要記住 “自上而下而下遞歸分裂,自下而上回溯更新” 從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)我們不斷地將區(qū)間一分為二,從葉子節(jié)點(diǎn)開始返回值,一直到根節(jié)點(diǎn),不斷地更新區(qū)間信息。

查找操作是線段樹的核心操作,考慮的情況相對(duì)較多,這里有四種情況:

情況一:節(jié)點(diǎn)區(qū)間包含查找區(qū)間。這種情況直接遞歸向下查找即可

情況二:節(jié)點(diǎn)區(qū)間不相交于查找區(qū)間。因?yàn)闆]有要查找的范圍,停止搜索

情況三:節(jié)點(diǎn)區(qū)間相交但不包含查找區(qū)間。將區(qū)間分成兩段,分別查找

情況四:節(jié)點(diǎn)區(qū)間相等于查找區(qū)間。直接返回答案

說(shuō)明一下,這里說(shuō)的 “包含” 的意思是一個(gè)區(qū)間全部元素都被另外一個(gè)區(qū)間涵蓋,“相交” 的意思是一個(gè)區(qū)間的部分元素被另外一個(gè)區(qū)間涵蓋,例如要查找的區(qū)間是 [1,3],那么 [0,4] 包含要查找的區(qū)間,[2,5] 只是相交要查找的區(qū)間。對(duì)于區(qū)間查找,后面有圖解,跟著例子走一遍印象會(huì)更深刻。

最后一個(gè)修改操作,和構(gòu)建操作類似,但有些許不同,你只需要記住 “自上而下遞歸查找,自下而上回溯更新”。修改的意思是,修改數(shù)組中的一個(gè)元素的值,這會(huì)影響相關(guān)的區(qū)間,相關(guān)的樹節(jié)點(diǎn),因此,相關(guān)聯(lián)的節(jié)點(diǎn)也就需要更新。

線段樹靈活的地方在于,樹節(jié)點(diǎn)中存放的數(shù)據(jù)不同,它的功能就不同,比如說(shuō),你想要求解區(qū)間和,那么樹節(jié)點(diǎn)中就存放對(duì)應(yīng)區(qū)間元素的和,你想求解區(qū)間上的最大值,那么樹節(jié)點(diǎn)中存放的就是對(duì)應(yīng)區(qū)間上的最大值。不過(guò)話說(shuō)回來(lái),線段樹并不是一個(gè)被廣泛應(yīng)用的數(shù)據(jù)結(jié)構(gòu),原因可能在于線段樹的構(gòu)建和使用相對(duì)于前綴和數(shù)組這樣的技巧來(lái)說(shuō),稍微復(fù)雜了些。但是在解決數(shù)組區(qū)間的問(wèn)題上,線段樹可以提供一個(gè)還不錯(cuò)的思考方向。

二、動(dòng)畫描述

三、代碼實(shí)現(xiàn)

publicclassSolution{ privateclassSegmentTreeNode{ intstart,end,max; SegmentTreeNodeleft,right; SegmentTreeNode(intstart,intend,intmax){ this.start=start; this.end=end; this.max=max; this.left=this.right=null; } } publicSegmentTreeNodebuild(intstart,intend,int[]nums){ if(start>end){ returnnull; } if(start==end){ returnnewSegmentTreeNode(start,end,nums[start]); } SegmentTreeNodenode=newSegmentTreeNode(start,end,nums[start]); //自上而下而下遞歸分裂 if(start!=end){ intmid=(start+end)/2; node.left=build(start,mid,nums); node.right=build(mid+1,end,nums); } //自下而上回溯更新 if(node.left!=null&&node.left.max>node.max){ node.max=node.left.max; } if(node.right!=null&&node.right.max>node.max){ node.max=node.right.max; } returnnode.max; } publicintquery(SegmentTreeNoderoot,intstart,intend){ //如果節(jié)點(diǎn)區(qū)間相等于查找區(qū)間,直接返回對(duì)應(yīng)的值即可 if(root.start==start&&root.end==end){ returnroot.max; } intmid=(root.start+root.end)/2; intleftMax=Integer.MIN_VALUE,rightMax=Integer.MIN_VALUE; //判斷是否需要去左子樹查找 if(start<=?mid)?{ ????????????//?節(jié)點(diǎn)相交查找區(qū)間的情況 ????????????if?(end?>mid){ leftMax=query(root.left,start,mid); }//節(jié)點(diǎn)包含查找區(qū)間的情況 else{ leftMax=query(root.left,start,end); } } //判斷是否需要去右子樹查找 if(mid=root.end){ return; } //自上而下遞歸查找 modify(root.left,index,value); modify(root.right,index,value); //自下而上回溯更新 root.max=Math.max(root.left.max,root.right.max); } }

四、復(fù)雜度分析

三個(gè)操作中,構(gòu)建樹的操作的時(shí)間復(fù)雜度是 O(n),原因也很好解釋,構(gòu)建的樹有 2n 個(gè)節(jié)點(diǎn),你可能會(huì)問(wèn)這個(gè) 2n 是怎么得到的,思考這個(gè)問(wèn)題可以從葉子節(jié)點(diǎn)出發(fā),一共有 n 個(gè)葉子節(jié)點(diǎn),構(gòu)建操作是從上往下不斷二分,這樣保證了樹的平衡,因此所有節(jié)點(diǎn)個(gè)數(shù)就是 n + n/2 + n/4 + ... + 1 = 2n。

由于構(gòu)建每個(gè)節(jié)點(diǎn)只花了 O(1) 的時(shí)間,因此整個(gè)構(gòu)建的時(shí)間復(fù)雜度就是 O(2n),忽略常數(shù)項(xiàng),也就是 O(n)。

修改和查找都是沿著一條或者幾條從上到下的路徑進(jìn)行的,因?yàn)闃涞母叨仁?O(logn),所以這兩個(gè)操作的時(shí)間復(fù)雜度也是 O(logn)??梢钥吹竭@個(gè)時(shí)間復(fù)雜度比暴力的 O(n) 還是快不少。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 數(shù)據(jù)結(jié)構(gòu)

    關(guān)注

    3

    文章

    573

    瀏覽量

    41551
  • 二叉樹
    +關(guān)注

    關(guān)注

    0

    文章

    74

    瀏覽量

    12921
  • 數(shù)組
    +關(guān)注

    關(guān)注

    1

    文章

    420

    瀏覽量

    27317

原文標(biāo)題:什么是線段樹?

文章出處:【微信號(hào):TheAlgorithm,微信公眾號(hào):算法與數(shù)據(jù)結(jié)構(gòu)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    無(wú)線傾角傳感器在古監(jiān)測(cè)中的應(yīng)用:以科技守護(hù)活文物的結(jié)構(gòu)安全

    無(wú)線傾角傳感器在古監(jiān)測(cè)中的應(yīng)用:以科技守護(hù)活文物的結(jié)構(gòu)安全
    的頭像 發(fā)表于 01-09 11:38 ?641次閱讀
    無(wú)線傾角傳感器在古<b class='flag-5'>樹</b>監(jiān)測(cè)中的應(yīng)用:以科技守護(hù)活文物的<b class='flag-5'>結(jié)構(gòu)</b>安全

    10個(gè)例子代碼,C語(yǔ)言結(jié)構(gòu)體的高級(jí)

    ;, current->data); current = current->next; } return 0; } 這個(gè)例子展示了結(jié)構(gòu)體的自引用,其中每個(gè)結(jié)構(gòu)體節(jié)點(diǎn)包含
    發(fā)表于 01-05 06:32

    每次用串口調(diào)試助手發(fā)送01之后,就會(huì)都到6個(gè)數(shù)據(jù),為什么?

    單片機(jī)通訊,發(fā)送01點(diǎn)亮個(gè)燈,再次發(fā)送熄滅。程序中不需要單片機(jī)發(fā)送數(shù)據(jù)給電腦,可是每次用串口調(diào)試助手發(fā)送01之后,就會(huì)都到6個(gè)數(shù)據(jù),不知道為什么,請(qǐng)高手指點(diǎn)。晶振是11.0592,波
    發(fā)表于 12-15 06:52

    實(shí)現(xiàn)個(gè)嵌入式的軟件定時(shí)器

    旦開始運(yùn)行,tickCnt將不停地加,而每個(gè)軟件定時(shí)器都記錄著個(gè)到期時(shí)間,只要tickCnt大于該到期時(shí)間,就代表定時(shí)器到期了。 3.2 數(shù)據(jù)結(jié)構(gòu) 軟件定時(shí)器的
    發(fā)表于 12-10 08:29

    typedef結(jié)構(gòu)體使用

    雖然結(jié)構(gòu)體的出現(xiàn)能夠讓我們有個(gè)更科學(xué)的數(shù)據(jù)結(jié)構(gòu)來(lái)管理數(shù)據(jù),但是每次使用結(jié)構(gòu)體都需要struct
    發(fā)表于 12-08 07:04

    C語(yǔ)言程序的結(jié)構(gòu)

    )(void); //處理程序   uInt8 ms_count; //時(shí)間片大小   } _op_;   數(shù)據(jù)結(jié)構(gòu)定義好之后,接著就是實(shí)現(xiàn)代碼,包括三部分,即初始化數(shù)據(jù)、時(shí)間片的刷新與時(shí)間到執(zhí)行
    發(fā)表于 11-26 08:12

    Verilog實(shí)現(xiàn)使用Booth編碼和Wallace的定點(diǎn)補(bǔ)碼乘法器原理

    萊士中,對(duì)于16位乘法,其每位至少包含6個(gè)全加器。對(duì)于32位乘法,全加器個(gè)數(shù)則為14。這樣子做可以保證對(duì)于首位,其有6/14個(gè)空閑的進(jìn)位要求,這至少可滿足n-2
    發(fā)表于 10-23 08:01

    關(guān)于E203內(nèi)核高性能乘法器優(yōu)化(

    乘法器和陣列乘法器都要困難,且資源消耗比迭代乘法器和陣列乘法器要多 2.4Wallace乘法器 線性陣列乘法器結(jié)構(gòu)簡(jiǎn)單實(shí)現(xiàn)起來(lái)較為容易,但每級(jí)只有
    發(fā)表于 10-23 06:09

    藍(lán)牙網(wǎng)關(guān)連接個(gè)數(shù)是多少

    我司藍(lán)牙網(wǎng)關(guān)標(biāo)準(zhǔn)版本是8個(gè)連接個(gè)數(shù),多連接版本是19個(gè)的連接個(gè)數(shù)。藍(lán)牙網(wǎng)關(guān)的“同時(shí)連接數(shù)”與信號(hào)質(zhì)量呈“此消彼長(zhǎng)”關(guān)系:連接數(shù)越多,留給每個(gè)從設(shè)備的時(shí)隙、帶寬和緩存越少,導(dǎo)致丟包率上升
    的頭像 發(fā)表于 10-11 16:02 ?663次閱讀
    藍(lán)牙網(wǎng)關(guān)連接<b class='flag-5'>個(gè)數(shù)</b>是多少

    分享個(gè)嵌入式學(xué)習(xí)階段規(guī)劃

    給大家分享個(gè)嵌入式學(xué)習(xí)階段規(guī)劃: ()基礎(chǔ)筑牢階段(約 23 天) 核心目標(biāo):打牢 C 語(yǔ)言、數(shù)據(jù)結(jié)構(gòu)、電路基礎(chǔ)C 語(yǔ)言開發(fā):學(xué)變量 / 指針 /
    發(fā)表于 09-12 15:11

    【HZ-T536開發(fā)板免費(fèi)體驗(yàn)】6、使用protoc-gen-gorm生成標(biāo)準(zhǔn)化的數(shù)據(jù)結(jié)構(gòu)

    在設(shè)計(jì)espnow協(xié)議的時(shí)候,考慮到我需要在esp32,Linux設(shè)備,web上使用相同的數(shù)據(jù)結(jié)構(gòu),那就需要考慮下,是否使用個(gè)通用的跨平臺(tái)序列化
    發(fā)表于 08-26 00:32

    科技預(yù)告新款人形機(jī)器人:有31個(gè)關(guān)節(jié)

    機(jī)器人似乎要搞大事了,宇科技發(fā)布了新款人形機(jī)器人的海報(bào),雖然配文只有“敬請(qǐng)期待”幾個(gè)字,但是根據(jù)海報(bào)信息顯示新款機(jī)器人配備有31個(gè)關(guān)節(jié)(海報(bào)顯示是6*2+3+7*2+2)。而且是
    的頭像 發(fā)表于 08-19 23:10 ?1997次閱讀

    程序設(shè)計(jì)與數(shù)據(jù)結(jié)構(gòu)

    《程序設(shè)計(jì)與數(shù)據(jù)結(jié)構(gòu)》重點(diǎn)闡述了三大方向內(nèi)容: 1. C語(yǔ)言學(xué)習(xí)中的痛點(diǎn):針對(duì)當(dāng)前工程師在C語(yǔ)言學(xué)習(xí)中的痛點(diǎn),如指針函數(shù)與函數(shù)指針,如何靈活應(yīng)用結(jié)構(gòu)體等。從變量的三要素(變量的類型,變量的值和變量
    發(fā)表于 05-13 16:45

    請(qǐng)問(wèn)K230D怎么將攝像頭采集的視頻數(shù)據(jù)通過(guò)串口輸出?

    我連了個(gè)WiFi模塊,想要將攝像頭采集的視頻數(shù)據(jù)通過(guò)串口發(fā)送出去。之前都是用的STM32,不太會(huì)MicroPython,搞不懂對(duì)象的數(shù)據(jù)結(jié)構(gòu),求教。
    發(fā)表于 04-28 06:16

    STM32H747I DSI模塊采用個(gè)數(shù)據(jù)通道無(wú)法顯示圖片怎么解決?

    在官方例程LCD_DSI_CmdMode_SingleBuffer中DSI采用的兩個(gè)數(shù)據(jù)通道與顯示屏通信,顯示屏可以正確顯示?,F(xiàn)在我希望采用個(gè)數(shù)據(jù)通道與顯示屏通信,于是我就在官方例程中做了
    發(fā)表于 03-07 08:11