欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

【c++提高1】二叉樹(shù)&二叉堆(萬(wàn)字總結(jié))-創(chuàng)新互聯(lián)

大綱 一、二叉樹(shù)

二叉樹(shù):1.二叉樹(shù)簡(jiǎn)介
二叉樹(shù):2.二叉樹(shù)的性質(zhì)
二叉樹(shù):3.二叉樹(shù)的存儲(chǔ)
二叉樹(shù):4.二叉樹(shù)的遍歷
二叉樹(shù):5.求解先序、后序、層次遍歷序列
二叉樹(shù):6.例題

創(chuàng)新互聯(lián)-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價(jià)比樂(lè)清網(wǎng)站開(kāi)發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫(kù),直接使用。一站式樂(lè)清網(wǎng)站制作公司更省心,省錢(qián),快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋樂(lè)清地區(qū)。費(fèi)用合理售后完善,十載實(shí)體公司更值得信賴。 二、二叉堆

二叉堆:1.二叉堆簡(jiǎn)介
二叉堆:2.二叉堆的插入操作
二叉堆:3.二叉堆的刪除堆頂操作
二叉堆:4.二叉堆復(fù)雜度分析
二叉堆:5.二叉堆代碼實(shí)現(xiàn)
二叉堆:6.優(yōu)先隊(duì)列
二叉堆:7.例題

二叉樹(shù) 一、二叉樹(shù)簡(jiǎn)介 (1)簡(jiǎn)介

二叉樹(shù)是N個(gè)節(jié)點(diǎn)的有限集合(N是自然數(shù)),當(dāng)N=0時(shí),那么就是一個(gè)空集合(叫空二叉樹(shù))。
總的來(lái)講(N>0的情況),二叉樹(shù)就是由一個(gè)根節(jié)點(diǎn)和兩棵子樹(shù)組成的。
然而,從名字就可以看出來(lái),二叉樹(shù)的每一個(gè)節(jié)點(diǎn)最多都只有兩棵子樹(shù)(分別稱為左子樹(shù)和右子樹(shù))

(2)二叉樹(shù)的形態(tài)(類別) 按照節(jié)點(diǎn)數(shù)分類: 空二叉樹(shù):

N=0
當(dāng)這個(gè)集合的節(jié)點(diǎn)數(shù)為0時(shí),稱為空二叉樹(shù)

只有一個(gè)根節(jié)點(diǎn)的二叉樹(shù):

N=1
需要滿足的條件:集合的節(jié)點(diǎn)樹(shù)為1

根節(jié)點(diǎn)只有左子樹(shù)

需要滿足的條件:根節(jié)點(diǎn)沒(méi)有右子樹(shù),只有左子樹(shù)

根節(jié)點(diǎn)只有右子樹(shù)

需要滿足的條件:根節(jié)點(diǎn)沒(méi)有左子樹(shù),只有右子樹(shù)

根節(jié)點(diǎn)左子樹(shù)和右子樹(shù)都有

需要滿足的條件:根節(jié)點(diǎn)的左子樹(shù)和右子樹(shù)都有

按照形態(tài)分類:

常見(jiàn)二叉樹(shù)形態(tài) \color{blue}常見(jiàn)二叉樹(shù)形態(tài) 常見(jiàn)二叉樹(shù)形態(tài)

斜樹(shù)

從名字就可以看出來(lái),斜樹(shù)是斜的,所以需要滿足條件:
所有的節(jié)點(diǎn)都只有左節(jié)點(diǎn)或者右節(jié)點(diǎn)
斜樹(shù)還分左斜樹(shù)和右斜樹(shù),每個(gè)節(jié)點(diǎn)都只有左節(jié)點(diǎn)的叫做左斜樹(shù),每個(gè)節(jié)點(diǎn)都只有右節(jié)點(diǎn)的叫做右斜樹(shù)

滿二叉樹(shù)

如果所有分支節(jié)點(diǎn)都存在左子樹(shù)和右子樹(shù),并且所有葉子節(jié)點(diǎn)都在同一層上,這樣的二叉樹(shù)稱為滿二叉樹(shù)

完全二叉樹(shù)

如果編號(hào)為i(1 ≤ i ≤ N)的結(jié)點(diǎn)與同樣深度的滿二叉樹(shù)中編號(hào)為i的節(jié)點(diǎn)在二叉樹(shù)中位置完全相同,則這棵二叉樹(shù)稱為完全二叉樹(shù)。

二、二叉樹(shù)的性質(zhì) 性質(zhì)1:在二叉樹(shù)的第i層上至多有2^(i-1)個(gè)節(jié)點(diǎn) 證明:設(shè)d(i)表示第i層的大節(jié)點(diǎn)數(shù)

每個(gè)節(jié)點(diǎn)至多有兩個(gè)子節(jié)點(diǎn):d(i)=d(i-1)*2
第一層是根節(jié)點(diǎn),只有一個(gè)節(jié)點(diǎn),所以:d(1)=1=2^(1-1)
第i層的大節(jié)點(diǎn)數(shù)d(i)=d(1)*2 ^ (i-1)=2 ^ (i-1)

性質(zhì)2:深度為k的二叉樹(shù)至多有2^k-1個(gè)節(jié)點(diǎn) 證明:設(shè)d(i)表示深度為i的二叉樹(shù)的大節(jié)點(diǎn)數(shù)

d(1)=1=2 ^ 1-1
d(2)=d(1)+2 ^ 1=2 ^ 1+2 ^ 1-1=2 ^ 2-1
d(3)=d(2)+2 ^ 2=2 ^ 2+2 ^ 2-1=2 ^ 3-1
d(k)=d(k-1)+2 ^ (k-1)=2 ^ (k-1)+2 ^ (k-1)-1=2 ^ k-1

性質(zhì)3:一棵二叉樹(shù)葉子節(jié)點(diǎn)數(shù)(設(shè)為n0)等于度為2的節(jié)點(diǎn)數(shù)(設(shè)為n2): 證明:

① 二叉樹(shù)中除了葉子節(jié)點(diǎn)外,剩下的節(jié)點(diǎn)要么度為1,要么度為2。(葉子節(jié)點(diǎn)度為0),
那么二叉樹(shù)的節(jié)點(diǎn)數(shù) n = n0 + n1 + n2(式子1)。
② 度為1的節(jié)點(diǎn)擁有1個(gè)孩子,度為2的節(jié)點(diǎn)擁有2個(gè)孩子,孩子結(jié)點(diǎn)總數(shù)為: n1+ 2n2 。
③ 二叉樹(shù)中,只有根節(jié)點(diǎn)不是孩子節(jié)點(diǎn),所以: n = n1 + 2n2 + 1 (式子2 )。
根據(jù)式子1和式子2可知: n0 + n1 + n2 = n1 + 2n2 + 1 ? n0 = n2 +1。

性質(zhì)4:具有n個(gè)結(jié)點(diǎn)的完全二叉樹(shù)的深度為log2(n)向下取整+1 證明:設(shè)完全二叉樹(shù)的深度為k,需證明: k=floor(log2(n))+1

根據(jù)完全二叉樹(shù)的定義可知:前k ? 1層一定是滿的。
根據(jù)二叉樹(shù)的性質(zhì)2可知:前k ? 1 層結(jié)點(diǎn)數(shù)為2 ^ (k-1)-1
2 ^ (k-1)-1對(duì)上面的獅子兩邊取對(duì)數(shù):k-1<=log2(n)得出k是整數(shù),所以k=floor(log2(n))+1成功證明

性質(zhì)5:編號(hào)為k的節(jié)點(diǎn)的左節(jié)點(diǎn)等于2k,右節(jié)點(diǎn)等于2k+1 額…沒(méi)啥好證的了 三、二叉樹(shù)的存儲(chǔ) 1.數(shù)組存儲(chǔ)

我們可以通過(guò)二叉樹(shù)的編號(hào)進(jìn)行存儲(chǔ),tr[i]表示編號(hào)為i的節(jié)點(diǎn)的信息。
我們可以通過(guò)剛才的性質(zhì)5,可以快速的得出編號(hào)為k的節(jié)點(diǎn):

雙親(父節(jié)點(diǎn))等于floor(k/2)
左節(jié)點(diǎn)等于2k
右節(jié)點(diǎn)等于2k+1

int trv[N];
void UpdateLeft(int p,int v)trv[p<<1]=v;//p<<1等效p*2
void UpdateRight(int p,int v)trv[p<<1|1]=v;//p<<1|1等效p*2+1,注意:s|1不一定等于s+1

并且在完全二叉樹(shù)的時(shí)候非常節(jié)省空間。
但是在非完全二叉樹(shù)的時(shí)候會(huì)比較浪費(fèi)空間,所以我們就要引出新的存儲(chǔ)方法——鏈表

2.鏈表存儲(chǔ)

由于二叉樹(shù)每個(gè)節(jié)點(diǎn)最多有兩個(gè)孩子,所以我們可以為其設(shè)計(jì)一個(gè)鏈表來(lái)存儲(chǔ)二叉樹(shù),這個(gè)鏈表叫二叉鏈表。

struct Edge{int dat;
	int LeftChild,RightChild;
}trv[N];
四、二叉樹(shù)的遍歷 先序遍歷

先序遍歷的規(guī)則是先根后左右

struct Edge{int dat;
	int LeftChild,RightChild;
}trv[N];
void Prnt(int idx){cout<if(!r)return;
	Prnt(r);                  //根
	PreODR(trv[r].LeftChild); //左
	PreODR(trv[r].RightChild);//右
}
中序遍歷

中序遍歷的規(guī)則是先左后根右

struct Edge{int dat;
	int LeftChild,RightChild;
}trv[N];
void Prnt(int idx){cout<if(!r)return;
	PreODR(trv[r].LeftChild);//左
	Prnt(r);                 //根
	PreODR(trv[r].RightChild);//右
}
后序遍歷

后序遍歷的規(guī)則是先左后右根

struct Edge{int dat;
	int LeftChild,RightChild;
}trv[N];
void Prnt(int idx){cout<if(!r)return;
	PreODR(trv[r].LeftChild);//左
	PreODR(trv[r].RightChild);//右
	Prnt(r);                 //根
}
層次遍歷

層次遍歷就和圖的bfs一樣,就是按照層次和每一個(gè)層次里的順序來(lái)遍歷

struct Edge{int dat;
	int LeftChild,RightChild;
}trv[N];
void Prnt(int idx){cout<queueq;q.push(r);
	Prnt(r);
	while(!q.empty()){int t=q.front();q.pop();
		if(trv[t].LeftChild){	Prnt(trv[t].LeftChild);
			q.push(trv[t].LeftChild);
		}
		if(trv[t].RightChild){	Prnt(trv[t].RightChild);
			q.push(trv[t].RightChild);
		}
	}
}
五、求解先序、后序、層次遍歷序列 1.中序后續(xù)求先序

方法1:
① 找根:基于后序序列的尾元素即是根,找出樹(shù)的根。
② 劃分子問(wèn)題:基于中序序列、根和后序序列,劃分出左右子樹(shù)的中序和后序序列。
③ 治理子問(wèn)題:基于左右子樹(shù)的中序和后序序列,遞歸的處理左右子樹(shù)。
④ 合并:將左右子樹(shù)根節(jié)點(diǎn)的存儲(chǔ)位置,合并為原樹(shù)的左右子樹(shù)。
⑤ 先序遍歷:基于構(gòu)建出的樹(shù),進(jìn)行先序遍歷,輸出先序序列。

struct Node{char dat;
	int l,r;
}tr[N];
int tot;
string in,ps;
int build(int ib,int ie,int pb,int pe){int r=++tot;tr[r].dat=ps[pe];
	int rps=in.find(tr[r].dat);
	interestinglen=rps-ib;
	if(rps>ib)tr[r].l=build(ib,rps-1,pb,pb+len-1);
	if(rpsif(!r)return;
	cout<cin>>in>>ps;
	int r=build(0,in.size()-1,0,ps.size()-1);
	ODR(r);
}

方法2:
在算法1的處理過(guò)程中直接輸出根,接著先遞歸處理左子樹(shù),再遞歸處理右子樹(shù)。

string in,ps;
void solve(int ib,int ie,int pb,int pe){char r=ps[pe];
	cout<ib)solve(ib,rps-1,pb,pb+len-1);
	if(rps
2.前序中序求后序

方法1:
① 找根:基于先序序列的首元素即是根,找出樹(shù)的根。
② 劃分子問(wèn)題:基于中序序列、根和先序序列,劃分出左右子樹(shù)的中序和先序序列。
③ 治理子問(wèn)題:基于左右子樹(shù)的中序和先序序列,遞歸的處理左右子樹(shù)。
④ 合并:將左右子樹(shù)根節(jié)點(diǎn)的存儲(chǔ)位置,合并為原樹(shù)的左右子樹(shù)。
⑤ 后序遍歷:基于構(gòu)建出的樹(shù),進(jìn)行后序遍歷,輸出后序序列。

struct Node{char dat;
	int l,r;
}tr[N];
int tot;
string in,pr;
int build(int ib,int ie,int pb,int pe){int r=++tot;
	tr[r].dat=pr[pb];
	int rps=in.find(tr[r].dat);
	int len=rps-ib;
	if(rps>ib)tr[r].l=build(ib,rps-1,pb+1,pb+len);
	if(rpsif(!r)return;
	ODR(tr[r].l);
	ODR(tr[r].r);
	cout<cin>>in>>pr;
	int r=build(0,in.size()-1,0,pr.size()-1);
	ODR(r);
}

方法2:
在算法1處理過(guò)程中,找到根后先儲(chǔ)存,當(dāng)遞歸處理完左右子樹(shù)后,再輸出根。

string in,pr;
void solve(int ib,int ie,int pb,int pe){char r=pr[pb];
	int rps=in.find(r);
	int len=rps-ib;
	if(rps>ib)solve(ib,rps-1,pb+1,rp+len);
	if(rpscin>>in>>pr;
	solve(0,in.size()-1,0,pr.size()-1);
}
3.前序中序求層次

① 找根:基于先序序列的首元素即是根,找出樹(shù)的根。
② 劃分子問(wèn)題:基于中序序列、根和先序序列,劃分出左右子樹(shù)的中序和先序序列。
③ 治理子問(wèn)題:基于左右子樹(shù)的中序和先序序列,遞歸的處理左右子樹(shù)。
④ 合并:將左右子樹(shù)根節(jié)點(diǎn)的存儲(chǔ)位置,合并為原樹(shù)的左右子樹(shù)。
⑤ 層次遍歷:基于構(gòu)建出的樹(shù),進(jìn)行層次遍歷,輸出層次序列。

struct Node{char dat;
	int l,r;
}tr[N];
int tot;
string in,pr;
int build(int ib,int ie,int pb,int pe){int r=++tot;
	tr[r].dat=pr[pb];
	int rps=in.find(tr[r].dat);
	int len=rps-ib;
	if(rps>ib)tr[r].l=build(ib,rps-1,pb+1,pb+len);
	if(rpscout<queueq;q.push(r);
	Prnt(r);
	while(!q.empty()){int n=q.ront();q.pop();
		if(tr[n].l){	Prnt(tr[n].l);
			q.push(tr[n].l);
		}
		if(tr[n].r){	Prnt(tr[n].r);
			q.push(tr[n].r);
		}
	}
}
int main(){cin>>in>>pr;
	int r=build(0,in.size()-1,0,pr.size()-1);
	bfs(r);
}
4.中序?qū)哟吻笙刃?p>① 找根:基于層次遍歷的首元素是整棵樹(shù)的根,找出樹(shù)根。
② 劃分子問(wèn)題:基于中序序列和根可以劃分出左右子樹(shù)的中序序列。

通過(guò)中序序列可以得到左子樹(shù)和右子樹(shù)各自所包含的所有節(jié)點(diǎn),左子樹(shù)的所有節(jié)點(diǎn)中最先
出現(xiàn)在層次遍歷序列中的節(jié)點(diǎn)是左子樹(shù)的根,同理可得右子樹(shù)的根。

string in,l;
int fr(int ib,int ie){for(int i=0;iint r=fr(ib,ie);cout<ib)solve(ib,r-1);
	if(rcin>>in>>l;solve(0,in.size()-1);
}
六、例題 1.小球下落-簡(jiǎn)化版
有一棵二叉樹(shù),大深度為D,且所有葉子的深度都相同。所有節(jié)點(diǎn)從上到下,從左到右的編號(hào)為1,2,3...,2^D-1.

在結(jié)點(diǎn)1處放一個(gè)小球,它會(huì)往下落,每個(gè)內(nèi)結(jié)點(diǎn)上都有一個(gè)開(kāi)關(guān)(開(kāi)關(guān)的狀態(tài)是false或true),初始時(shí)全部是false狀態(tài),當(dāng)每次有小球落到這個(gè)結(jié)點(diǎn)上時(shí),開(kāi)關(guān)的狀態(tài)被改變。

當(dāng)小球達(dá)到一個(gè)內(nèi)結(jié)點(diǎn)時(shí),如果該結(jié)點(diǎn)的開(kāi)關(guān)狀態(tài)是關(guān)閉的,則小球往左走,否則往右走,直到走到葉子結(jié)點(diǎn)。

如下圖所示:



表示結(jié)點(diǎn)編號(hào)為1,2,3...15,大深度為4的完全二叉樹(shù),由于初始時(shí),所有的結(jié)點(diǎn)的開(kāi)關(guān)狀態(tài)是false,所以第一個(gè)球下落時(shí)經(jīng)過(guò)結(jié)點(diǎn)1 2 4最終落在結(jié)點(diǎn)8上,第二個(gè)球下落時(shí)經(jīng)過(guò)結(jié)點(diǎn)1 3 6最終落在結(jié)點(diǎn)12上,第三個(gè)球下落時(shí),經(jīng)過(guò)結(jié)點(diǎn)1 2 5最終落在結(jié)點(diǎn)10上。

現(xiàn)在給出多組測(cè)試數(shù)據(jù),最多包含1000組,每組測(cè)試數(shù)據(jù)兩個(gè)值。第一個(gè)值是D,表示二叉樹(shù)的大深度。第二個(gè)值是L,表示小球的個(gè)數(shù)L。

假設(shè)I不超過(guò)整棵樹(shù)的葉子個(gè)數(shù),2≤D≤20,and 1≤L≤5000

編寫(xiě)一個(gè)程序,計(jì)算出小球從節(jié)點(diǎn)1處依次開(kāi)始下落,最后一個(gè)小球L將會(huì)落下哪里?輸出第L個(gè)小球最后所在的葉子編號(hào)。

輸入格式
第一行一個(gè)整數(shù)n,表示測(cè)試數(shù)據(jù)的組數(shù)

接下來(lái)n行,每行兩個(gè)整數(shù)分別表示二叉樹(shù)的深度D和小球的個(gè)數(shù)L,用空格隔開(kāi)

最后一行,“-1”,表示測(cè)試數(shù)據(jù)結(jié)束

輸出格式
輸出n行,分別表示每組測(cè)試數(shù)據(jù),第L個(gè)小球最后所在的葉子編號(hào)

輸入輸出樣列
輸入樣例1:
5
4 2
3 4
10 1
2 2
8 128
-1
輸出樣例1:
12
7
512
3
255

這道題就是個(gè)大大大大大氵題,直接按照題目的思路模擬即可。

#include#define debug(x) cout<< #x<< '='<< x<< '\n';
using namespace std;
bool tr[1000010]; //lson=t*2,rson=t*2+1
int T;
void slove(){memset(tr,0,sizeof(tr));
	int D,L;scanf("%d%d",&D,&L);
	int a=(1<int now=1;
		while(now	int t=now;
			if(!tr[now])now=now<<1;
			else now=now<<1|1;
			tr[t]^=1;
		}x=now;
	}
	printf("%d\n",x);
}
int main () {scanf("%d",&T);
	while(T--)slove();
	return 0;
}
2.美國(guó)血統(tǒng) American Heritage [USACO 3.4]
農(nóng)夫約翰非常認(rèn)真地對(duì)待他的奶牛們的血統(tǒng).然而他不是一個(gè)真正優(yōu)秀的記帳員.他把他的奶牛們的家譜作成二叉樹(shù),并且把二叉樹(shù)以更線性的”樹(shù)的中序遍歷“和”樹(shù)的前序遍歷“的符號(hào)加以記錄而不是用圖形的方法.

你的任務(wù)是在被給予奶牛家譜的”樹(shù)中序遍歷“和”樹(shù)前序遍歷“的符號(hào)后,創(chuàng)建奶牛家譜的”樹(shù)的后序遍歷“的符號(hào)。每一頭奶牛的姓名被譯為一個(gè)唯一的字母. (你可能已經(jīng)知道你可以在知道樹(shù)的兩種遍歷以后可以經(jīng)常地重建這棵樹(shù).)顯然,這里的樹(shù)不會(huì)有多余 26 個(gè)的頂點(diǎn).

這是在樣例輸入和 樣例輸出中的樹(shù)的圖形表達(dá)方式:

                 C
                /   \
               /     \
              B       G
             / \     /
            A   D   H
               / \
              E   F
樹(shù)的中序遍歷是按照左子樹(shù),根,右子樹(shù)的順序訪問(wèn)節(jié)點(diǎn)。

樹(shù)的前序遍歷是按照根,左子樹(shù),右子樹(shù)的順序訪問(wèn)節(jié)點(diǎn)。

樹(shù)的后序遍歷是按照左子樹(shù),右子樹(shù),根的順序訪問(wèn)節(jié)點(diǎn)。

輸入格式
第一行: 樹(shù)的中序遍歷

第二行: 同樣的樹(shù)的前序遍歷

輸出格式
單獨(dú)的一行表示該樹(shù)的后序遍歷.

輸入輸出樣列
輸入樣例1:
ABEDFCHG
CBADEFGH
輸出樣例1:
AEFDBHGC

模板題啊。

#include#define debug(x) cout<< #x<< '='<< x<< '\n';
using namespace std;
string p, i;
void build (string p, string i) {if (p.empty ()) return;
    char r = p[0];
    int k = i.find (r);
    p.erase (p.begin ());
    string l1 = p.substr (0, k);
    string r1 = p.substr (k);
    string l2 = i.substr (0, k);
    string r2 = i.substr (k + 1);
    build (l1, l2);
    build (r1, r2);
    cout<< r;
}
int main () {cin >>i >>p;
    build (p, i);
	return 0;
}
二叉堆 一、二叉堆簡(jiǎn)介

二叉堆使用完全二叉樹(shù)實(shí)現(xiàn),分為大根堆和小根堆兩種:
大根堆:任意一個(gè)分支結(jié)點(diǎn)的值都大于或者等于其子節(jié)點(diǎn)的值。
小根堆:任意一個(gè)分支結(jié)點(diǎn)的值都小于或者等于其子節(jié)點(diǎn)的值。

查詢大值(大根堆)和最小值(小根堆)時(shí),直接取根節(jié)點(diǎn)即可,時(shí)間復(fù)雜度O(1) 二、二叉堆的插入操作

插入操作要求在不影響二叉堆性質(zhì)的前提下,在二叉堆中添加一個(gè)新元素。
性質(zhì)1:完全二叉樹(shù)結(jié)構(gòu),插入新元素后需要繼續(xù)保持完全二叉樹(shù)的結(jié)構(gòu)。
性質(zhì)2:任何一個(gè)分支節(jié)點(diǎn)的值都大于等于(大根堆)或小于等于(小根堆)其子節(jié)點(diǎn)的值。

① 堆尾插入:每次在堆尾插入新元素(確保插入后仍然是完全二叉樹(shù)結(jié)構(gòu))。
② 向上調(diào)整(和父節(jié)點(diǎn)比較),將新元素調(diào)整到合適的位置。

三、二叉堆的刪除堆頂操作

刪頂操作要求在不影響二叉堆性質(zhì)的前提下,將堆頂元素刪除。
性質(zhì)1:完全二叉樹(shù)結(jié)構(gòu),刪除堆頂后需要繼續(xù)保持完全二叉樹(shù)的結(jié)構(gòu)。
性質(zhì)2:任何一個(gè)分支節(jié)點(diǎn)的值都大于等于(大根堆)或小于等于(小根堆)其子節(jié)點(diǎn)的值。

① 將堆頂賦值為堆尾元素的值,接著刪除堆尾節(jié)點(diǎn)。(保持完全二叉樹(shù)結(jié)構(gòu))
② 向下調(diào)整(和孩子節(jié)點(diǎn)比較),堆頂元素調(diào)整到合適的位置。

我們可以通過(guò)數(shù)組來(lái)實(shí)現(xiàn)這個(gè)二叉堆! 四、二叉堆復(fù)雜度分析

插入操作:堆尾添加元素時(shí)間復(fù)雜度O(1),向上調(diào)整的次數(shù)大為完全二叉樹(shù)的層數(shù):
log2 n + 1,故插入操作的時(shí)間復(fù)雜度為:O(log2 n )。
刪頂操作:堆頂復(fù)制和堆尾刪除時(shí)間復(fù)雜度O(1), 向下調(diào)整的次數(shù)大為完全二叉樹(shù)
的層數(shù): log2 n + 1,故刪頂操作的時(shí)間復(fù)雜度為:O(log2 n )。

五、二叉堆代碼實(shí)現(xiàn)
int heap[N],tt;
bool empty(){return !tt;}
int sz(){return tt;}
int tp(){return heap[1];}
int psh(int v){heap[++tt]=v;
	int x=tt;
	while(x>1&&heap[x]>1]){swap(heap[x>>1],heap[x]);
		x>>=1;
	}
}
void pop(){heap[1]=heap[tt--];
	int x=1,p=x<<1;
	while(p<=tt){if(p+1<=tt&&heap[p+1]
六、優(yōu)先隊(duì)列

優(yōu)先隊(duì)列priority_queue和堆是實(shí)現(xiàn)的相近的功能:插入一個(gè)數(shù)和刪除最小或大的值
常用函數(shù):
在這里插入圖片描述
優(yōu)先隊(duì)列也是可以使用小根堆和大根堆的,分別是greater(上升)、less(下降)
就比如:

priority_queue,greater>qg;
priority_queue,less>ql;

然后就比如插入一個(gè)數(shù)x:

q.push(x);

刪除隊(duì)頭(同前面的堆頂):

q.pop();

同樣,優(yōu)先隊(duì)列的類型也可以是結(jié)構(gòu)體,但是需要重載運(yùn)算符。
大根堆需要重載小于運(yùn)算符

struct Node{int a;
	bool operator<(const Node&W)const{return a>W.a;
	}
}
priority_queue,less>q;

小根堆需要重載大于運(yùn)算符

struct Node{int a;
	bool operator<(const Node&W)const{return a,greater>q;
七、例題
有兩個(gè)長(zhǎng)度都是N的序列A和B,在A和B中各取一個(gè)數(shù)相加可以得到N^2個(gè)和,求這N^2個(gè)和中最小的N個(gè)。

輸入格式
第一行一個(gè)正整數(shù)N;

第二行N個(gè)整數(shù)Ai,滿足Ai<=Ai+1且Ai<=10^9;(i和i+1表示序列的下標(biāo))

第三行N個(gè)整數(shù)Bi, 滿足Bi<=Bi+1且Bi<=10^9。(i和i+1表示序列的下標(biāo))

輸出格式
輸出僅一行,包含N個(gè)整數(shù),從小到大輸出這N個(gè)最小的和,相鄰數(shù)字之間用空格隔開(kāi)。

輸入輸出樣列
輸入樣例1:
3
2 6 6
1 4 8
輸出樣例1:
3 6 7
說(shuō)明
【數(shù)據(jù)規(guī)模】

對(duì)于50%的數(shù)據(jù)中,滿足1<=N<=1000;

對(duì)于100%的數(shù)據(jù)中,滿足1<=N<=100000。

在這里插入圖片描述
同樣的反過(guò)來(lái)統(tǒng)計(jì)也一樣:

#includeusing namespace std;
typedef pairPII; 
const int N=1e5+10;
int n,a[N],b[N],t[N];
priority_queue,greater>q;
int main(){cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<=n;i++)cin>>b[i];
	for(int i=1;i<=n;i++)q.push(make_pair(a[1]+b[i],i)),t[i]=1;
	for(int i=1;i<=n;i++){cout<

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

本文題目:【c++提高1】二叉樹(shù)&二叉堆(萬(wàn)字總結(jié))-創(chuàng)新互聯(lián)
轉(zhuǎn)載注明:http://chinadenli.net/article30/pshso.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供建站公司定制網(wǎng)站網(wǎng)站建設(shè)做網(wǎng)站搜索引擎優(yōu)化云服務(wù)器

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)