




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
前端程序員面試分類真題21簡(jiǎn)答題1.
給定一個(gè)沒(méi)有排序的鏈表,去掉其重復(fù)項(xiàng),并保留原順序,例如鏈表1->3->1->5->5->7,去掉重復(fù)項(xiàng)后變?yōu)?->3->5->7。正確答案:通過(guò)雙重循環(huán)直接(江南博哥)在鏈表上進(jìn)行刪除操作。外層循環(huán)用一個(gè)指針從第一個(gè)結(jié)點(diǎn)開(kāi)始遍歷整個(gè)鏈表,然后內(nèi)層循環(huán)用另外一個(gè)指針遍歷其余結(jié)點(diǎn),將與外層循環(huán)遍歷到的指針?biāo)附Y(jié)點(diǎn)的數(shù)據(jù)域相同的結(jié)點(diǎn)刪除,如下圖所示。
雙重循環(huán)的刪除演示
假設(shè)外層循環(huán)從outerCur開(kāi)始遍歷,當(dāng)內(nèi)層循環(huán)指針innerCur遍歷到上圖虛線所框的位置(outerCur.data==innerCur.data)時(shí),需要把innerCur指向的結(jié)點(diǎn)刪除。具體步驟如下:
(1)用tmp記錄待刪除結(jié)點(diǎn)的地址。
(2)為了能夠在刪除tmp結(jié)點(diǎn)后繼續(xù)遍歷鏈表中其余的結(jié)點(diǎn),使innerCur指向它的后繼結(jié)點(diǎn):innerCur=innerCur.next。
(3)從鏈表中刪除tmp結(jié)點(diǎn)。
實(shí)現(xiàn)代碼如下所示。
//鏈表結(jié)點(diǎn)
functionnode(id,data){
this.id=id;
//結(jié)點(diǎn)id
this.data=data;
//結(jié)點(diǎn)數(shù)據(jù)
this.next=null;
//下一結(jié)點(diǎn)
}
//單鏈表
functionlinkList(id,data){
this.header=newnode(id,data);
//鏈表頭結(jié)點(diǎn)
}
linkLtotype={
addLink:function(node){
//添加結(jié)點(diǎn)數(shù)據(jù)
varcurrent=this.header;
while(current.next!=null){
if(current.next,id>node.id){
break;
}
current=current.next;
}
node.next=current.next;
current.next=node;
},
clear:function(){
//清空鏈表
this.header=null;
},
getLinkList:function(){
//獲取鏈表
varcurrent=this.header;
if(current,next==null){
console.log("鏈表為空");
return;
}
vartxt="";
while(current.next!=null){
txt+=current.next.data+"";
if(current.next.next==null){
break;
}
current=current.next;
}
console.log(txt);
},
removeDup:function(){
//刪除帶頭結(jié)點(diǎn)的無(wú)序單鏈表中重復(fù)的結(jié)點(diǎn)
varhead=this.header;
if(head==null||head.next==null)
return;
varouterCur=head.next,
//外層循環(huán)指針,指向鏈表的第一個(gè)結(jié)點(diǎn)
innerCur=null,
//內(nèi)層循環(huán)用來(lái)遍歷ourterCur后面的結(jié)點(diǎn)
innerPre=null,
//innerCur的前驅(qū)結(jié)點(diǎn)
tmp=null;
//用來(lái)指向被刪除結(jié)點(diǎn)的指針
for(;outerCur!=null;outerCur=outerCur.next){
for(innerCur=outerCur.next,innerPre=outerCur;innerCur!=null;){
//找到重復(fù)的結(jié)點(diǎn)并刪除
if(outerCur.data==innerCur.data){
tmp=innerCur;
innerPre.next=innerCur.next;
innerCur=innerCur.next;
}else{
innerPre=innerCur;
innerCur=innerCur.next;
}
}
}
}
};
varlists=newlinkList();
lists.addLink(newnode(1,1));
lists.addLink(newnode(2,3));
lists.addLink(newnode(3,1));
lists.addLink(newnode(4,5));
lists.addLink(newnode(5,5));
lists.addLink(newnode(6,7));
console.log("刪除重復(fù)結(jié)點(diǎn)前:");
Iists.getLinkList();
//131557
console.log("刪除重復(fù)結(jié)點(diǎn)后:");
lists.removeDup();
lists.getLinkList();
//1357
//釋放鏈表所占的空間
lists.clear();[考點(diǎn)]鏈表
2.
給定兩個(gè)單鏈表,鏈表的每個(gè)結(jié)點(diǎn)代表一位數(shù),計(jì)算兩個(gè)數(shù)的和。例如:輸入鏈表(3->1->5)和鏈表(5->9->2),輸出:8->0->8,即513+295=808,注意個(gè)位數(shù)在鏈表頭。正確答案:對(duì)鏈表中的結(jié)點(diǎn)直接進(jìn)行相加操作,把和存儲(chǔ)到新的鏈表對(duì)應(yīng)的結(jié)點(diǎn)中,同時(shí)還要記錄結(jié)點(diǎn)相加后的進(jìn)位,如下圖所示。
結(jié)點(diǎn)相加
使用這個(gè)方法需要注意如下幾個(gè)問(wèn)題:①每組結(jié)點(diǎn)進(jìn)行相加后需要記錄其是否有進(jìn)位;②如果兩個(gè)鏈表H1與H2的長(zhǎng)度不同(長(zhǎng)度分別為L(zhǎng)1和L2,且L1<L2),當(dāng)對(duì)鏈表的第L1位計(jì)算完成后,接下來(lái)只需要考慮鏈表L2剩余的結(jié)點(diǎn)值(需要考慮進(jìn)位);③對(duì)鏈表所有結(jié)點(diǎn)都完成計(jì)算后,還需要考慮此時(shí)是否還有進(jìn)位,如果有進(jìn)位,則需要增加新的結(jié)點(diǎn),此結(jié)點(diǎn)的數(shù)據(jù)域?yàn)?。實(shí)現(xiàn)代碼如下所示。
//鏈表結(jié)點(diǎn)
functionnode(id,name){
this.id=id;
//結(jié)點(diǎn)id
=name;
//結(jié)點(diǎn)名稱
this.next=null;
//下一結(jié)點(diǎn)
}
//單鏈表
functionlinkList(id,name){
this.header=newnode(id,name);
//鏈表頭結(jié)點(diǎn)
}
linkLtotype={
addLink:function(node){
//添加結(jié)點(diǎn)數(shù)據(jù)
varcurrent=this.header;
while(current.next!=null){
if(current.next.id>node.id){
break;
}
current=current.next;
}
node.next=current.next;
current.next=node;
},
clear:function(){
//清空鏈表
this.header=null;
},
getLinkList:function(){
//獲取鏈表
varcurrent=this.header;
if(current.next==null){
console.log("鏈表為空");
return;
}
vartxt="";
while(current.next!=null){
txt+=+"";
if(current.next.next==null){
break;
}
current=current.next;
}
console.log(txt);
}
};
/*
**函數(shù)功能:兩個(gè)帶頭結(jié)點(diǎn)的單鏈表所代表的數(shù)相加
**輸入?yún)?shù):h1:第一個(gè)鏈表;h2:第二個(gè)鏈表
**返回值:相加后鏈表的頭結(jié)點(diǎn)
*/
functionadd(h1,h2){
h1=h1.header;
h2=h2.header;
if(h1==null||h1.next==null)
returnh2;
if(h2=null||h2.next==null)
returnh1;
varc=0,//用來(lái)記錄進(jìn)位
sum=0,
//用來(lái)記錄兩個(gè)結(jié)點(diǎn)相加的值
p1=h1.next,
//用來(lái)遍歷h1
p2=h2.next,
//用來(lái)遍歷h2
tmp=null,
//用來(lái)指向新創(chuàng)建的存儲(chǔ)相加和的結(jié)點(diǎn)
resultHead=newlinkList(),
//相加后鏈表頭結(jié)點(diǎn)
p=resultHead;
//用來(lái)指向鏈表resultHead最后一個(gè)結(jié)點(diǎn)
while(p1&&p2){
tmp=newlinkList();
sum=++c;
tmp,=sum%10;
//兩結(jié)點(diǎn)相加和
c=Math.floor(sum/10);
//進(jìn)位
p.header.next=tmp;
p=tmp;
p1=p1.next;
p2=p2.next;
}
//鏈表h2比h1長(zhǎng),接下來(lái)只需要考慮h2剩余結(jié)點(diǎn)的值
if(p1==null){
while(p2){
tmp=newlinkList();
sum=+c;
=sum%10;
c=Math.floor(sum/10);
p.header.next=tmp;
p=tmp;
p2=p2.next;
}
}
//鏈表h1比h2長(zhǎng),接下來(lái)只需要考慮h1剩余結(jié)點(diǎn)的值
if(p2==null){
while(p1){
tmp=newlinkList();
sum=+c;
=sum%10;
c=Math.floor(sum/10);
p.header.next=tmp;
p=tmp;
p1=p1.next;
}
}
//如果計(jì)算完成后還有進(jìn)位,則增加新的結(jié)點(diǎn)
if(c==1){
tmp=newlinkList();
=1;
p.header.next=tmp;
}
returnresultHead;
}
varhead1=newlinkList(),
head2=newlinkList();
for(vari=1;i<7;1++){
head1.addLink(newnode(i,i+2));
}
varnum=0;
for(i=9;i>4;1--){
head2.addLink(newnode(num,i));
num++;
}
console.log("Head1:");
head1.getLinkList();
//345678
console.log("Head2;");
head2.getLinkList();
//98765
console.log("相加后:");
varaddResult=add(head1,head2),
txt="";
while(addResult!=null){
if(addR)
txt+=addR+"";
addResult=addResult.header.next;
}
console.log(txt);
//233339
//釋放鏈表所占的空間
head1.clear();
head2.clear();[考點(diǎn)]鏈表
3.
給定鏈表L0->L1->L2->…->Ln-1->Ln,把鏈表重新排序?yàn)長(zhǎng)0->Ln->L1->Ln-1->L2->Ln-2->…。要求:①在原來(lái)鏈表的基礎(chǔ)上進(jìn)行排序,即不能申請(qǐng)新的結(jié)點(diǎn);②只能修改結(jié)點(diǎn)的next域,不能修改數(shù)據(jù)域。正確答案:主要思路如下所列:
(1)找到鏈表的中間結(jié)點(diǎn)。
(2)對(duì)鏈表的后半部分子鏈表進(jìn)行逆序。
(3)把鏈表的前半部分子鏈表與逆序后的后半部分子鏈表進(jìn)行合并,合并的思路為從兩個(gè)鏈表中各取一個(gè)結(jié)點(diǎn)進(jìn)行合并。實(shí)現(xiàn)方法如下圖所示。
重新排序思路
實(shí)現(xiàn)代碼如下所示。
//鏈表結(jié)點(diǎn)
functionnode(id,data){
this.id=id;
//結(jié)點(diǎn)id
this.data=data;
//結(jié)點(diǎn)數(shù)據(jù)
this.next=null;
//下一結(jié)點(diǎn)
}
//單鏈表
functionlinkList(id,data){
this.header=newnode(id,data);
//鏈表頭結(jié)點(diǎn)
}
linkLtotype={
addLink:function(node){
//添加結(jié)點(diǎn)數(shù)據(jù)
varcurrent=this.header;
while(current.next!=null){
if(current.next.id>node.id){
break;
}
current=current.next;
}
node.next=current,next;
current,next=node;
},
clear:function(){
//清空鏈表
this.header=null;
},
getLinkList:function(){
//獲取鏈表
varcurrent=this.header;
if(current.next==null){
console.log("鏈表為空");
return;
}
vartxt="";
while(current.next!=null){
txt+=current.next.data+"";
if(current.next.next==null){
break;
}
current=current.next;
}
console.log(txt);
},
/*
**函數(shù)功能:找出鏈表的中間結(jié)點(diǎn),把鏈表從中間分成兩個(gè)子鏈表
**輸入?yún)?shù):head,鏈表頭結(jié)點(diǎn)
**返回值:指向鏈表中間結(jié)點(diǎn)的指針
*/
FindMiddleNode:function(head){
if(head==null||head.next==null)
returnhead;
varfast=head,
//快指針每次走兩步
slow=head,
//慢指針每次走一步
slowPre=head;
//當(dāng)fast到鏈表尾部時(shí),slow恰好指向鏈表的中間結(jié)點(diǎn)
while(fast!=null&&fast.next!=null){
slowPre=slow;
slow=slow.next;
fast=fast.next.next;
}
//把鏈表分成兩個(gè)獨(dú)立的子鏈表
slowPre.next=null;
returnslow;
},
/*
**函數(shù)功能:對(duì)不帶頭結(jié)點(diǎn)的單鏈表進(jìn)行翻轉(zhuǎn)
**輸入?yún)?shù):head,指向鏈表頭結(jié)點(diǎn)
*/
Reverse:function(head){
if(head==null||head.next==null)
returnhead;
varpre=head,
//前驅(qū)結(jié)點(diǎn)
cur=head.next,
//當(dāng)前結(jié)點(diǎn)
next=cur.next;
//后繼結(jié)點(diǎn)
pre.next=null;
//使當(dāng)前遍歷到的結(jié)點(diǎn)cur指向其前驅(qū)結(jié)點(diǎn)
while(cur!=null){
next=cur.next;
cur.next=pre;
pre=cur;
cur=cur.next;
cur=next;
}
returnpre;
},
/*
**函數(shù)功能:對(duì)鏈表進(jìn)行排序
*/
Reorder:function(){
varhead=this.header;
//指向鏈表頭結(jié)點(diǎn)
if(head==null||head.next==null)
return;
varcur1=head.next,
//前半部分鏈表的第一個(gè)結(jié)點(diǎn)
mid=this.FindMiddleNode(head.next),
cur2=this.Reverse(mid),
//后半部分鏈表逆序后的第一個(gè)結(jié)點(diǎn)
tmp=null;
//合并兩個(gè)鏈表
while(cur1.next!=null){
tmp=cur1.next;
cur1.next=cur2;
cur1=tmp;
tmp=cur2.next;
cur2.next=cur1;
cur2=tmp;
}
cur1.next=cur2;
}
};
varlists=newlinkList();
for(vari=1;i<8;i++){
lists.addLink(newnode(i,i));
}
console.log("排序前:");
lists.getLinkList();
//1234567
lists.Reorder();
console.log("排序后:");
lists.getLinkList();
//1726354
//釋放鏈表所占的空間
lists.clear();[考點(diǎn)]鏈表
4.
找出單鏈表中的倒數(shù)第k個(gè)元素,例如給定單鏈表:1->2->3->4->5->6->7,則單鏈表的倒數(shù)第3(即k=3)個(gè)元素為5。正確答案:由于單鏈表只能從頭到尾依次訪問(wèn)鏈表的各個(gè)結(jié)點(diǎn),所以,如果要找鏈表的倒數(shù)第k個(gè)元素,也只能從頭到尾進(jìn)行遍歷查找。在查找過(guò)程中,設(shè)置兩個(gè)指針,讓其中一個(gè)指針比另一個(gè)指針先前移k步,然后兩個(gè)指針同時(shí)往前移動(dòng)。循環(huán)到先行的指針值為null時(shí),另一個(gè)指針?biāo)傅奈恢镁褪撬业奈恢?。程序代碼如下所示。
//鏈表結(jié)點(diǎn)
functionnode(id,data){
this.id=id;
//結(jié)點(diǎn)id
this.data=data;
//結(jié)點(diǎn)數(shù)據(jù)
this.next=null;
//下一結(jié)點(diǎn)
}
//單鏈表
functionlinkList(id,data){
this.header=newnode(id,data);
//鏈表頭結(jié)點(diǎn)
}
linkLtotype={
addLink:function(node){
//添加結(jié)點(diǎn)數(shù)據(jù)
varcurrent=this.header;
while(current.next!=null){
if(current.next.id>node.id){
break;
}
current=current.next;
}
node.next=current.next;
current.next=node;
},
clear:function(){
//清空鏈表
this.header=null;
},
getLinkList:function(){
//獲取鏈表
varcurrent=this.header;
if(current.next==null){
console.log("鏈表為空");
return;
}
vartxt="";
while(current.next!=null){
txt+=current.next.data+"";
if(current.next,next==null){
break;
}
current=current.next;
}
console.log(txt);
},
FindLastK:function(k){
//找出鏈表倒數(shù)第k個(gè)結(jié)點(diǎn)
varhead=this.header;
if(head==null||head.next==null)
returnhead;
varslow=null,
fast=null;
slow=fast=head.next;
for(vari=0;i<k&&fast;++i){
//前移k步
fast=fast.next;
}
//判斷k是否已超出鏈表長(zhǎng)度
if(i<k)
returnnull;
while(fast!=null){
slow=slow.next;
fast=fast.next;
}
returnslow;
}
};
varlists=newlinkList();
for(vari=1;i<8;i++){
lists.addLink(newnode(i,i));
}
console.log("鏈表:");
lists.getLinkList();
//1234567
console.log("鏈表倒數(shù)第3個(gè)元素為:");
varresult=lists.FindLastK(3);
console.log(result.data);
//5
//釋放鏈表所占的空間
lists.clear();[考點(diǎn)]鏈表
5.
隊(duì)列和棧有什么區(qū)別?正確答案:棧與隊(duì)列是在程序設(shè)計(jì)中被廣泛使用的兩種重要的線性數(shù)據(jù)結(jié)構(gòu),它們都是在一個(gè)特定范圍的存儲(chǔ)單元中存儲(chǔ)的數(shù)據(jù),這些數(shù)據(jù)都可以重新被取出使用。與線性表相比,它們的插入和刪除操作受到了更多的約束和限定,故又被稱為限定性的線性表結(jié)構(gòu)。兩者不同的是,棧就像一個(gè)很窄的桶,先存進(jìn)去的數(shù)據(jù)只能最后被取出來(lái),是LIFO(LastInFirstOut,后進(jìn)先出),它將進(jìn)出順序逆序,即先進(jìn)后出,后進(jìn)先出,棧結(jié)構(gòu)如下圖1所示。隊(duì)列像日常排隊(duì)買東西的人的“隊(duì)列”,先排隊(duì)的人先買,后排隊(duì)的人后買,是FIFO(FirstInFirstOut,先進(jìn)先出),它保持進(jìn)出順序一致,即先進(jìn)先出,后進(jìn)后出,隊(duì)列結(jié)構(gòu)如下圖2所示。
圖1棧結(jié)構(gòu)示意圖
圖2隊(duì)列結(jié)構(gòu)示意圖
需要注意的是,有時(shí)在數(shù)據(jù)結(jié)構(gòu)中還有可能出現(xiàn)按照大小排隊(duì)或按照一定條件排隊(duì)的數(shù)據(jù)隊(duì)列,這時(shí)的隊(duì)列屬于特殊隊(duì)列,就不一定按照“先進(jìn)先出”的原則讀取數(shù)據(jù)了。[考點(diǎn)]棧和隊(duì)列
6.
實(shí)現(xiàn)一個(gè)棧的數(shù)據(jù)結(jié)構(gòu),使其具有以下方法:壓棧、彈棧、取棧頂元素、判斷棧是否為空以及獲取棧中元素個(gè)數(shù)。正確答案:在采用數(shù)組來(lái)實(shí)現(xiàn)棧的時(shí)候,主要面臨的問(wèn)題是給數(shù)組申請(qǐng)多大的存儲(chǔ)空間比較合理,因?yàn)樵谑褂脳5臅r(shí)候并不確定以后棧中需要存放的數(shù)據(jù)元素的個(gè)數(shù),申請(qǐng)多了會(huì)造成空間的浪費(fèi),而申請(qǐng)少了則會(huì)導(dǎo)致不夠用。為了便于理解,這里采用的方法是給定一個(gè)初始值,假如這個(gè)值是10,那么就先申請(qǐng)能存儲(chǔ)10個(gè)元素的數(shù)組作為棧的存儲(chǔ)空間。在后期使用的過(guò)程中如果空間不夠用了,再擴(kuò)大這個(gè)空間。實(shí)現(xiàn)思路如下圖所示。
數(shù)組模擬的棧結(jié)構(gòu)
從圖中能夠看出,可以把數(shù)組的首地址當(dāng)作棧底,同時(shí)記錄棧中元素的個(gè)數(shù)size,可見(jiàn),根據(jù)棧底指針和size就可以計(jì)算出棧頂?shù)牡刂妨?。假設(shè)數(shù)組首地址為arr,從圖中可以看出,壓棧的操作其實(shí)是把待壓棧的元素放到數(shù)組Arr[size]中,然后執(zhí)行size++操作;同理,彈棧操作其實(shí)是取數(shù)組中的Arr[size-1]元素,然后執(zhí)行size--操作。根據(jù)這個(gè)原理可以非常容易地實(shí)現(xiàn)棧,示例代碼如下所示。
//創(chuàng)建一個(gè)空數(shù)組作為棧
varstack=[];
//獲取棧頂元素
functiongetTop(stack){
returnstack[stack.length-1];
}
//向數(shù)組壓入一個(gè)元素
stack.push(1);
stack.push(2);
//輸出棧頂元素
console.log(getTop(stack));
//2
//讓棧頂元素出棧
stack.pop();
console.log(getTop(stack));
//1[考點(diǎn)]棧和隊(duì)列
7.
實(shí)現(xiàn)一個(gè)隊(duì)列的數(shù)據(jù)結(jié)構(gòu),使其具有入隊(duì)列、出隊(duì)列、查看隊(duì)列首尾元素、查看隊(duì)列大小等功能。正確答案:下圖給出了一種最簡(jiǎn)單的實(shí)現(xiàn)方式,用front來(lái)記錄隊(duì)列首元素的位置,用rear來(lái)記錄隊(duì)列尾元素往后一個(gè)位置。入隊(duì)列的時(shí)候只需要將待入隊(duì)列的元素放到數(shù)組下標(biāo)為rear的位置,同時(shí)rear++,出隊(duì)列的時(shí)候只需要執(zhí)行front++即可。
數(shù)組模擬的隊(duì)列結(jié)構(gòu)
為了簡(jiǎn)化實(shí)現(xiàn)過(guò)程,下面代碼定義的隊(duì)列最大的空間為10,實(shí)現(xiàn)代碼如下所示。
functionqueue(){
this.queueList=[];
this.size=0;
}
totype={
enQueue:function(data){
//入隊(duì)操作
this.queueList[this.size++]=data;
returnthis;
},
outQueue:function(){
//出隊(duì)操作
if(!this.isEmpty()){
--this.size;
varfront=this.queueList.splice(0,1);
returnfront[0];
}
returnfalse;
},
getQueue:function(){
//獲取隊(duì)列
returnthis.queueList;
},
getFront:function(){
//獲取隊(duì)頭元素
if(!this.isEmpty()){
returnthis.queueList[0];
}
returnfalse;
},
getRear:function(){
//獲取隊(duì)尾元素
if(!this.isEmpty()){
varlen=this.queueList.length;
returnthis.queueList[len-1];
}
returnfalse;
},
getSize:function(){
//獲取隊(duì)列的長(zhǎng)度
returnthis.size;
},
isEmpty:function(){
//檢測(cè)隊(duì)列是否為空
return()===this.size;
}
};
varqueue=newqueue();
queue.enQueue(1);
queue.enQueue(2);
console.log("隊(duì)列頭元素為:",queue.getFront());
//1
console.log("隊(duì)列尾元素為:",queue.getRear());
//2
console.log("隊(duì)列大小為:",queue.getSize());
//2[考點(diǎn)]棧和隊(duì)列
8.
翻轉(zhuǎn)(也叫顛倒)棧的所有元素,例如輸入棧{1,2,3,4,5},其中,1在棧頂,翻轉(zhuǎn)之后的棧為{5,4,3,2,1},其中,5在棧項(xiàng)。正確答案:最容易想到的辦法是申請(qǐng)一個(gè)額外的隊(duì)列,先把棧中的元素依次出棧放到隊(duì)列里,然后把隊(duì)列里的元素按照出隊(duì)列的順序入棧,這樣就可以實(shí)現(xiàn)棧的翻轉(zhuǎn),這種方法的缺點(diǎn)是需要申請(qǐng)額外的空間存儲(chǔ)隊(duì)列,因此,空間復(fù)雜度較高。下面介紹一種空間復(fù)雜度較低的遞歸方法。
遞歸程序有兩個(gè)關(guān)鍵因素需要注意:遞歸定義和遞歸終止條件。經(jīng)過(guò)分析后,很容易得到該問(wèn)題的遞歸定義和遞歸終止條件。遞歸定義:將當(dāng)前棧的最底元素移到棧頂,其他元素順次下移一位,然后對(duì)不包含棧頂元素的子棧進(jìn)行同樣的操作。終止條件:遞歸下去,直到棧為空。遞歸的調(diào)用過(guò)程如圖1所示。
圖1翻轉(zhuǎn)棧的遞歸過(guò)程
在圖1中,對(duì)棧{1,2,3,4,5}進(jìn)行翻轉(zhuǎn)的操作為:首先把棧底元素移動(dòng)到棧頂?shù)玫綏5,1,2,3,4},然后對(duì)不包含棧頂元素的子棧進(jìn)行遞歸調(diào)用(對(duì)子棧元素進(jìn)行翻轉(zhuǎn)),子棧{1,2,3,4}翻轉(zhuǎn)的結(jié)果為{4,3,2,1},因此,最終得到翻轉(zhuǎn)后的棧為{5,4,3,2,1}。
此外,由于棧的后進(jìn)先出的特點(diǎn),使得只能取棧頂?shù)脑?。因此,要把棧底的元素移?dòng)到棧頂也需要遞歸調(diào)用才能完成,主要思路為:把不包含該棧頂元素的子棧棧底元素移動(dòng)到子棧的棧頂,然后把棧頂?shù)脑嘏c子棧棧頂?shù)脑?其實(shí)就是與棧頂相鄰的元素)進(jìn)行交換。
圖2子棧的遞歸過(guò)程
為了容易理解遞歸調(diào)用,可以認(rèn)為在進(jìn)行遞歸調(diào)用的時(shí)候,子棧已經(jīng)實(shí)現(xiàn)把棧底元素移動(dòng)到棧頂。在圖2中為了把棧{1,2,3,4,5}的棧底元素5移動(dòng)到棧頂,首先對(duì)子棧{2,3,4,5}進(jìn)行遞歸調(diào)用,調(diào)用的結(jié)果為{5,2,3,4},然后將子棧棧頂元素5與棧頂元素1進(jìn)行交換得到棧{5,1,2,3,4},從而把棧底元素移動(dòng)到了棧頂。示例代碼如下。
functionLNode(){
this.mElem=null;
this.mNext=null;
}
functionStackLinked(){
this.mNext=null;
//頭"指針",指向棧頂元素
this.mLength=0;
//棧內(nèi)元素個(gè)數(shù)
}
StackLtotype={
/**
*判斷棧是否為空棧
*@returnboolean如果為空棧返回true,否則返回false
*/
getlsEmpty:function(){
returnthis.mNext==null;
},
/**
*將所有元素出棧
*@returnarray返回所有棧內(nèi)元素
*/
getAllPopStack:function(){
vare=[];
if(!this.getIsEmpty()){
while(this.mNext!=null){
e.push(this.mNext.mElem);
this.mNext=this.mNext.mNext;
}
}
this.mLength=0;
returne;
},
/**
*返回棧內(nèi)元素個(gè)數(shù)
*@returnint
*/
getLength:function(){
returnthis.mLength;
},
/**
*元素入棧
*@parammixede入棧元素值
*@returnvoid
*/
push:function(e){
varnewLn=newLNode();
newLn.mElem=e;
newLn.mNext=this.mNext;
this.mNext=newLn;
this,mLength++;
},
/**
*元素出棧
*@returnboolean出棧成功返回true,否則返回false
*/
pop:function(){
if(this.getIsEmpty()){
returnfalse;
}
varp=this.mNext,
e=p,mElem;
this.mNext=p.mNext;
this.mLength--;
returntrue;
},
/**
*僅返回棧內(nèi)所有元素
*@returnarray棧內(nèi)所有元素組成的一個(gè)數(shù)組
*/
getAllElem:function(){
varsldata=[],
p;
if(!this.getlsEmpty()){
p=this,mNext;
while(p!=null){
sldata.push(p.mElem);
p=p.mNext;
}
}
returnsldata;
},
/**
*返回棧頂元素
*@returnelement返回棧頂元素
*/
top:function(){
if(this.getIsEmpty()){
returnfalse;
}
varlist=this.getAllElem();
returnlist[0];
},
/**
*把棧底元素移動(dòng)到棧頂
*/
move_bottom_to_top:function(){
if(this,getIsEmpty())
return;
vartop1=this.top(),
top2;
this.pop();
//彈出棧頂元素
if(!this.getIsEmpty()){
//遞歸處理不包含棧頂元素的子棧
this.move_bottom_to_top();
top2=this.top();
this.pop();
//交換棧項(xiàng)元素與子棧棧頂元素
this.push(top1);
this.push(top2);
}else{
this.push(top1);
}
},
/**
*翻轉(zhuǎn)棧
*/
reverse_stack:function(){
if(this.getIsEmpty())
return;
//把棧底元素移動(dòng)到棧頂
this.move_bottom_to_top();
vartop=this.top();
this.pop();
//遞歸處理子棧
this.reverse_stack();
this.push(top);
}
};
varstack=newStackLinked();
stack.push('5');
stack.push('4');
stack.push('3');
stack.push('2');
stack.push('1');
stack.reverse_stack();
console.log("翻轉(zhuǎn)后的出棧順序?yàn)?");
vartxt="";
while(!stack.getIsEmpty()){
txt+=stack.top()+"";
stack.pop();
}
console.log(txt);
//54321[考點(diǎn)]棧和隊(duì)列
9.
輸入兩個(gè)整數(shù)序列,其中一個(gè)序列表示棧的push(入)順序,判斷另一個(gè)序列有沒(méi)有可能是對(duì)應(yīng)的pop(出)順序。正確答案:假如輸入的push序列是1、2、3、4、5,那么3、2、5、4、1就有可能是一個(gè)pop序列,但5、3、4、1、2就不可能是它的一個(gè)pop序列。
主要思路是使用一個(gè)棧來(lái)模擬入棧順序,具體步驟如下:
(1)把push序列依次入棧,直到棧頂元素等于pop序列的第一個(gè)元素,然后棧頂元素出棧,pop序列移動(dòng)到第二個(gè)元素。
(2)如果棧頂繼續(xù)等于pop序列現(xiàn)在的元素,則繼續(xù)出棧并將pop序列后移;否則對(duì)push序列繼續(xù)入棧。
(3)如果push序列已經(jīng)全部入棧,但是pop序列未全部遍歷,而且棧頂元素不等于當(dāng)前pop元素,那么這個(gè)序列不是一個(gè)可能的出棧序列。如果棧為空,而且pop序列也全部被遍歷過(guò),則說(shuō)明這是一個(gè)可能的pop序列。下圖給出一個(gè)合理的pop序列判斷過(guò)程。
pop序列的判斷過(guò)程
在圖中,(1)~(3)三步,由于棧頂元素不等于pop序列的第一個(gè)元素3,因此,1、2、3依次入棧;當(dāng)3入棧后,棧頂元素等于pop序列的第一個(gè)元素3,因此,第(4)步執(zhí)行3出棧;然后指向pop序列的第二個(gè)元素2,且棧頂元素等于pop序列的當(dāng)前元素,因此,第(5)步執(zhí)行2出棧;再接著由于棧頂元素4不等于當(dāng)前pop序列5,因此,接下來(lái)的(6)和(7)兩步分別執(zhí)行4和5入棧;緊接著由于棧頂元素5等于pop序列的當(dāng)前值,因此,第(8)步執(zhí)行5出棧;接下來(lái)(9)和(10)兩步棧頂元素都等于當(dāng)前pop序列的元素,因此,都執(zhí)行出棧操作;最后棧為空,同時(shí)pop序列都完成了遍歷,說(shuō)明{3,2,5,4,1}是一個(gè)合理的出棧序列。實(shí)現(xiàn)代碼如下所示。
functionLNode(){
this.mElem=null;
this.mNext=null;
}
functionStackLinked(){
this.mNext=null;
//頭"指針",指向棧頂元素
this.mLength=0;
//棧內(nèi)元素個(gè)數(shù)
}
StackLtotype={
/**
*判斷棧是否為空棧
*@returnboolean如果為空棧返回true,否則返回false
*/
getIsEmpty:function(){
returnthis.mNext==null;
},
***
*將所有元素出棧
*@returnarray返回所有棧內(nèi)元素
*/
getAllPopStack:function(){
vare=[];
if(!this.getIsEmpty()){
while(this.mNext!=null){
e.push(this.mNext.mElem);
this.mNext=this.mNext.mNext;
}
}
this,mLength=0;
returne;
},
/**
*返回棧內(nèi)元素個(gè)數(shù)
*@returnint
*/
getLength:function(){
returnthis.mLength;
},
/**
*元素入棧
*@parammixede入棧元素值
*@returnvoid
*/
push:function(e){
varnewLn=newLNode();
newLn.mElem=e;
newLn.mNext=this.mNext;
this.mNext=newLn;
this.niLength++;
},
/**
*元素出棧
*@returnboolean出棧成功返回true,否則返回false
*/
pop:function()(
if(this.getIsEmpty()){
returnfalse;
}
varp=this.mNext,
e=p.mElem;
this.mNext=p.mNext;
this.mLength--;
returntrue;
},
/**
*僅返回棧內(nèi)所有元素
*@returnarray棧內(nèi)所有元素組成的一個(gè)數(shù)組
*/
getAllElem:function(){
varsldata=[],
p;
if(!this.getIsEmpty())
{
p=this.mNext;
while(p!=null){
sldata.push(p.mElem);
p=p.mNext;
}
}
returnsldata;
},
/**
*返回棧頂元素
*@returnelement返回棧頂元素
*/
top:function(){
if(this.getIsEmpty()){
returnfalse;
}
varlist=this.getAllElem();
returnlist[0];
}
};
/**
*根據(jù)入棧序列判斷出棧后和另一個(gè)的出棧序列是否相等
*/
functionisPopSerial(push,pop){
if(push.getIsEmpty()||pop.getIsEmpty())
returnfalse;
varpushLen=push,getLength(),
popLen=pop.getLength();
if(pushLen!=popLen)
returnfalse;
varpushIndex=0,
popIndex=0,
stack=newStackLinked(),
pushList=push.getAllElem(),
popList=pop.getAllElem();
while(pushIndex<pushLen){
//把push序列依次入棧,直到棧頂元素等于pop序列的第一個(gè)元素
stack.push(pushList[pushIndex]);
pushIndex++;
//棧頂元素出棧,pop序列移動(dòng)到下一個(gè)元素
while(!stack.getIsEmpty()&&stack.top()==popList[popIndex]){
stack.pop();
popIndex++;
}
}
//棧為空,且pop序列中元素都被遍歷過(guò)
returnstack.getIsEmpty()&&popIndex==popLen;
}
varstackPUSH=newStackLinked(),
stackPOP=newStackLinked(),
push=";
for(vari=1;i<=5;1++){
stackPUSH.push(i);
push+=i;
}
stackPOP.push(5);
stackPOP.push(2);
stackPOP.push(1);
stackPOP.push(4);
stackPOP.push(3);
console.log(isPopSerial(stackPUSH,stackPOP));
//true[考點(diǎn)]棧和隊(duì)列
10.
如何用O(l)的時(shí)間復(fù)雜度求棧中最小元素?正確答案:由于棧具有后進(jìn)先出的特點(diǎn),因此,push和pop只能對(duì)棧頂元素進(jìn)行操作??梢杂昧硗庖粋€(gè)變量來(lái)記錄棧底的位置,通過(guò)遍歷棧中所有的元素找出最小值,但是這種方法的時(shí)間復(fù)雜度為O(N)。那么如何才能用O(l)的時(shí)間復(fù)雜度求出棧中最小的元素呢?
在算法設(shè)計(jì)中,經(jīng)常會(huì)采用空間換取時(shí)間的方式來(lái)降低時(shí)間復(fù)雜度,也就是說(shuō)采用額外的存儲(chǔ)空間來(lái)降低操作的時(shí)間復(fù)雜度。具體而言,在實(shí)現(xiàn)的時(shí)候使用兩個(gè)棧結(jié)構(gòu),一個(gè)棧用來(lái)存儲(chǔ)數(shù)據(jù),另外一個(gè)棧用來(lái)存儲(chǔ)棧的最小元素。實(shí)現(xiàn)思路如下:如果當(dāng)前入棧的元素比原來(lái)?xiàng)V械淖钚≈颠€小,則把這個(gè)值壓入保存最小元素的棧中;在出棧的時(shí)候,如果當(dāng)前出棧的元素恰好為當(dāng)前棧中的最小值,保存最小值的棧頂元素也出棧,使得當(dāng)前最小值變?yōu)楫?dāng)前最小值入棧之前的那個(gè)最小值。為了簡(jiǎn)單化,可以在棧中保存整數(shù)類型。代碼實(shí)現(xiàn)如下所示。
functionNode(){
this.data=null;
this.min=null;
}
functionMin_Stack(a){
var_this=this;
this.data=[];
this.top=0;
a.forEach(function(value,key){
_this.push(value);
});
}
Min_Stotype={
push:function(i){
varnode=newNode();
node.data=i;
/**
*此處設(shè)置每個(gè)節(jié)點(diǎn)的min值,設(shè)置方法為,若棧為空,
*當(dāng)前元素data則為當(dāng)前節(jié)點(diǎn)的min,
*若棧非空,則當(dāng)前元素data與前一個(gè)節(jié)點(diǎn)的min值比較,
*取其小者作為當(dāng)前節(jié)點(diǎn)的min。
*/
if(this.top==0){
min=node.data;
}else{
min=this.data[this.top-1].min<node.data?
this.data[this.top-1].min:
node.data;
}
node.min=min;
this.data.push(node);
this.top++;
returnnode;
},
pop:function(){
varr=this.data[--this.top];
this.data.splice(this.top,1);
returnr;
},
get_min:function(){
returnthis.data[this.top-1].min;
}
};
vara=[5],
min_stack=newMin_Stack(a);
console.log("棧中最小值為:",min_stack.get_min());
//5
min_stack.push(6);
console.log("棧中最小值為:",min_stack.get_min());
//5
min_stack.push(2);
console.log("棧中最小值為:",min_stack.get_min());
//2
min_stack.pop();
console.log("棧中最小值為:",min_stack.get_min());
//5[考點(diǎn)]棧和隊(duì)列
11.
如何用兩個(gè)棧模擬隊(duì)列操作?正確答案:題目要求用兩個(gè)棧來(lái)模擬隊(duì)列,假設(shè)使用棧A與棧B模擬隊(duì)列Q,其中A為插入棧,B為彈出棧。再假設(shè)A和B都為空,可以認(rèn)為棧A提供入隊(duì)列的功能,棧B提供出隊(duì)列的功能。
要入隊(duì)列,入棧A即可,而出隊(duì)列則需要分兩種情況考慮:
(1)如果棧B不為空,則直接彈出棧B的數(shù)據(jù)。
(2)如果棧B為空,則依次彈出棧A的數(shù)據(jù),放入棧B中,再?gòu)棾鰲的數(shù)據(jù)。
代碼實(shí)現(xiàn)如下所示。
vararr1=[],
//棧A
arr2=[];
//棧B
functionpush(node){
arr1.push(node);
}
functionpop(){
if(arr2.length>0){
returnarr2.pop();
}
while(arr1.length>0){
arr2.push(arr1.pop());
}
returnarr2.pop();
}
push(1);
push(2);
console.log("隊(duì)列首元素為:",pop());//1
console.log("隊(duì)列首元素為:",pop());//2[考點(diǎn)]棧和隊(duì)列
12.
什么叫二叉樹(shù)?正確答案:二叉樹(shù)(BinaryTree)也稱為二分樹(shù)、二元樹(shù)或?qū)Ψ謽?shù)等,它是n(n≥0)個(gè)有限元素的集合,該集合或者為空、或者由一個(gè)稱為根(root)的元素及兩個(gè)不相交的、被分別稱為左子樹(shù)和右子樹(shù)的二叉樹(shù)組成。當(dāng)集合為空時(shí),稱該二叉樹(shù)為空二叉樹(shù)。
在二叉樹(shù)中,一個(gè)元素也稱作一個(gè)結(jié)點(diǎn)。二叉樹(shù)的遞歸定義為:二叉樹(shù)或者是一棵空樹(shù),或者是一棵由一個(gè)根結(jié)點(diǎn)和兩棵互不相交的分別稱作根結(jié)點(diǎn)的左子樹(shù)和右子樹(shù)所組成的非空樹(shù),左子樹(shù)和右子樹(shù)又同樣都是一棵二叉樹(shù)。[考點(diǎn)]二叉樹(shù)
13.
一棵完全二叉樹(shù)上有1001個(gè)結(jié)點(diǎn),其中葉子結(jié)點(diǎn)的個(gè)數(shù)是多少?正確答案:二叉樹(shù)的公式:n=n0+n1+n2=n0+n1+(n0-1)=2×n0+n1-1。而在完全二叉樹(shù)中,n1只能取0或1。若n1=1,則2×n0=1001,可推出n0為小數(shù),不符合題意;若n1=0,則2×n0-1=1001,則n0=501。所以,答案為501。[考點(diǎn)]二叉樹(shù)
14.
如果根的層次為1,具有61個(gè)結(jié)點(diǎn)的完全二叉樹(shù)的深度為多少?正確答案:根據(jù)二叉樹(shù)的性質(zhì),具有n個(gè)結(jié)點(diǎn)的完全二叉樹(shù)深度為[log2n]+1,因此,含有61個(gè)結(jié)點(diǎn)的完全二叉樹(shù)深度為6層。所以,答案為6。[考點(diǎn)]二叉樹(shù)
15.
在具有100個(gè)結(jié)點(diǎn)的樹(shù)中,其邊的數(shù)目為多少?正確答案:在一棵樹(shù)中,除了根結(jié)點(diǎn)之外,每一個(gè)結(jié)點(diǎn)都有一條入邊,因此,總邊數(shù)應(yīng)該是100-1,即99條。所以,答案為99。[考點(diǎn)]二叉樹(shù)
16.
什么是平衡二叉樹(shù)?正確答案:平衡二叉樹(shù)(Balanced.BinaryTree)又被稱為AVL樹(shù),它是一棵空樹(shù)或它的左右兩個(gè)子樹(shù)的深度差的絕對(duì)值不超過(guò)1,并且左右兩個(gè)子樹(shù)都是一棵平衡二叉樹(shù)。[考點(diǎn)]二叉樹(shù)
17.
如何用JavaScript實(shí)現(xiàn)二叉樹(shù)?正確答案:使用數(shù)組構(gòu)造一棵二叉樹(shù),將二叉樹(shù)的每個(gè)結(jié)點(diǎn)存儲(chǔ)到數(shù)組中,數(shù)組的鍵名代表二叉樹(shù)的結(jié)點(diǎn),數(shù)組的鍵值代表二叉樹(shù)的結(jié)點(diǎn)值。初始化時(shí),創(chuàng)建一個(gè)指定長(zhǎng)度的二叉樹(shù),設(shè)置數(shù)組的第一個(gè)值為根結(jié)點(diǎn)。代碼實(shí)現(xiàn)如下所示。
/**
*用數(shù)組表示的二叉樹(shù)
*/
functionBinaryTree(size,root){
this.size=size;
this.array=[];
for(i=0;i<size;i+){
this.array[i]=i;
}
this.array[0]=root;
}
BinaryTtotype={
searchNode:function(nodeCode){
//查詢結(jié)點(diǎn)
if(nodeCode>=this.size||nodeCode<0){
returnfalse;
}
returnthis.array[nodeCode];
},
addNode:function(nodeCode,place,nodeValue){
//增加樹(shù)結(jié)點(diǎn)
jf(nodeCode<this.size||nodeCode<0){
returnfalse;
}
//當(dāng)添加左孩子時(shí),索引加1;當(dāng)添加右孩子時(shí),索引加2
varindex=place==0?(nodeCode+1):(nodeCode+2);
//存在nodeCode這個(gè)結(jié)點(diǎn)就結(jié)束接下來(lái)的添加操作
if(this.array[nodeCode+1]){
returnfalse;
}
//新結(jié)點(diǎn)在相應(yīng)位置補(bǔ)值
if(nodeCode>=this.size){
for(vari=this.size;i<nodeCode+1;i++){
this.array[i]=i;
}
this.size=index;
}
this.array[index]=nodeValue;
},
deleteNode:function(nodeCode){
//刪除樹(shù)結(jié)點(diǎn)
if(nodeCode>=this.size||nodeCode<0){
returnfalse;
}
this.array.splice(nodeCode,1);
},
showTree:function(){//遍歷樹(shù)
vartxt="";
this.array.forEach(function(value,key){
txt+=value+"";
});
console.log(txt);
}
};
//產(chǎn)生一個(gè)以2為根結(jié)點(diǎn),9個(gè)子結(jié)點(diǎn)的二叉樹(shù)
varBinaryTree=newBinaryTree(10,2);
console.log("初始化的二叉樹(shù):");
BinaryTree.showTree();
//2123456789
console,log("搜索根結(jié)點(diǎn):");
console.log(BinaryTree.searchNode(0));//2
BinaryTree.addNode(10,1,0);
console.log("增加0結(jié)點(diǎn)后的二叉樹(shù):");
BinaryTree.showTree();
//2123456789100
BinaryTree.deleteNode(1);
//刪除根結(jié)點(diǎn)的下一個(gè)結(jié)點(diǎn)
console.log("刪除根結(jié)點(diǎn)下一個(gè)結(jié)點(diǎn)后的二叉樹(shù):");
BinaryTree,showTree();
//223456789100[考點(diǎn)]二叉樹(shù)
18.
如何把一個(gè)有序整數(shù)數(shù)組放到二叉樹(shù)中?正確答案:如果要把一個(gè)有序的整數(shù)數(shù)組放到二叉樹(shù)中,那么所構(gòu)建出來(lái)的二叉樹(shù)必定也是一棵有序的二叉樹(shù)。鑒于此,實(shí)現(xiàn)思路為:取數(shù)組的中間元素作為根結(jié)點(diǎn),將數(shù)組分成兩部分,對(duì)數(shù)組的兩部分用遞歸的方法分別構(gòu)建左右子樹(shù)。如下圖所示。
數(shù)組構(gòu)建二叉樹(shù)的過(guò)程
如圖所示,首先取數(shù)組的中間結(jié)點(diǎn)6作為二叉樹(shù)的根結(jié)點(diǎn),把數(shù)組分成左右兩部分,然后對(duì)于數(shù)組的左右兩部分子數(shù)組分別運(yùn)用同樣的方法進(jìn)行二叉樹(shù)的構(gòu)建,例如對(duì)于左半部分子數(shù)組,取中間結(jié)點(diǎn)3作為樹(shù)的根結(jié)點(diǎn),再把數(shù)組分成左右兩部分。以此類推,就可以完成二叉樹(shù)的構(gòu)建,實(shí)現(xiàn)代碼如下所示。
varprintTxt="";
//要在控制臺(tái)輸出的文本
/**
*二叉樹(shù)的定義
*用指定的值構(gòu)建二叉樹(shù),并定義左右子樹(shù)
*@parammixedkey
結(jié)點(diǎn)值
*@parammixedleft
左子樹(shù)結(jié)點(diǎn)
*@parammixedright
右子樹(shù)結(jié)點(diǎn)
*/
functionBinaryTree(key,left,right){
this.key=key||null;
this.left=left;
this.right=right;
}
BinaryTtotype={
/**
*檢測(cè)當(dāng)前結(jié)點(diǎn)是否是葉子結(jié)點(diǎn)
*@returnboolean當(dāng)結(jié)點(diǎn)非空并且有兩個(gè)空的子樹(shù)時(shí)為true,否則為false
*/
isLeaf:function(){
return!this.isEmpty()&&
this.left.isEmpty()&&
this.right.isEmpty();
},
/**
*檢測(cè)結(jié)點(diǎn)是否為空
*@returnboolean如果結(jié)點(diǎn)為空返回true,否則為false
*/
isEmpty:function(){
returnthis.key===null;
},
getKey:function(){
//讀取結(jié)點(diǎn)值
if(this.isEmpty()){
returnfalse;
}
returnthis.key;
},
attachKey:function(obj){
//給結(jié)點(diǎn)指定值
if(!this.isEmpty())
returnfalse;
this.key=obj;
this.left=newBinaryTree();
this.right=newBinaryTree();
},
detachKey:function(){
//刪除結(jié)點(diǎn)值,使得結(jié)點(diǎn)為空
if(!this.isLeaf())
returnfalse;
this.key=null;
this.left=null;
this.right=null;
returnthis.key;
},
getLeft:function(){
//讀取左子樹(shù)
if(this.isEmpty())
returnfalse;
returnthis.left;
},
getRight:function(){
//讀取右子樹(shù)
if(this.isEmpty())
returnfalse;
returnthis.right;
},
preorderTraversal:function(){
//前序遍歷
if(this.isEmpty()){
return;
}
printTxt+="+this.getKey();
this.getLeft().preorderTraversal();
this.getRight().preorderTraversal();
},
inorderTraversal:function(){
//中序遍歷
if(this,isEmpty()){
return;
}
this.getLeft().inorderTraversal();
printTxt+="+this.getKey();
this.getRight().inorderTraversal();
},
postorderTraversal:function(){
//后序遍歷
if(this,isEmpty()){
return;
}
this.getLeft().postorderTraversal();
this.getRight().postorderTraversal();
printTxt+="+this.getKey();
},
insert:function(obj){
//給二叉排序樹(shù)插入指定值
if(this.isEmpty()){
this.attachKey(obj);
return;
}
vardiff=pare(obj);
if(diff<0)
this.getLeft().insert(obj);
elseif(diff>0)
this.getRight().insert(obj);
},
compare:function(obj){
//當(dāng)前結(jié)點(diǎn)值與傳入的值做比較
returnobj-this.getKey();
}
};
vararr=[1,2,3,4,5,6,7,8,9,10],
txt=arr.reduce(function(accumulator,current,index,array){
returnaccumulator+""+current;
});
console.log("數(shù)組:",tXt);
//12345678910
varroot=newBinaryTree();
/**
*對(duì)數(shù)組的兩部分用遞歸的方法分別構(gòu)建左右子樹(shù)
*/
functionsetTree(arr,root){
varlen=arr.length;
if(len<2){
root.insert(arr[0]);
return;
}
varmiddle=Math.floor(len/2),
left=arr.slice(0,middle),
//數(shù)組的左邊部分
right=arr.slice(middle+1);
//數(shù)組的右邊部分
root.insert(arr[middle]);
//添加中間結(jié)點(diǎn)
setTree(left,root.left);
//左子樹(shù)
if(len>2)
setTree(right,root.right);
//右子樹(shù)
}
setTree(arr,root);
root.inorderTraversal();
//中序遍歷
console.log("轉(zhuǎn)換成樹(shù)的中序遍歷為:",printTxt);//12345678910[考點(diǎn)]二叉樹(shù)
19.
假設(shè)存在以下省市區(qū)結(jié)構(gòu)的數(shù)組,需要按多層級(jí)結(jié)構(gòu)排序輸出,請(qǐng)使用JavaScript代碼實(shí)現(xiàn)該功能。
varitems=[
{'id':1,'pid':0,'name':'江西省'},
{'id':2,'pid':0,'name':'黑龍江省'},
{'id':3,'pid':1,'name':'南昌市'},
{'id':4,'pid':2,'name':'哈爾濱市'},
{'id':5,'pid':2,'name':'雞西市'},
{'id':6,'pid':4,'name':'香坊區(qū)'},
{'id':7,'pid':4,'name':'南崗區(qū)'},
{'id':8,'pid':6,'name':'和興路'},
{'id':9,'pid':7,'name':'西大直街'},
{'id':10,'pid':8,'name':'東北林業(yè)大學(xué)'},
{'id':11,'pid':9,'name'
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 保安證考試各科目分析試題及答案
- 解密考試流程的保安證試題及答案
- 2025年保安證考試探秘之旅試題及答案
- 提高保安證考試成功率的方程式試題及答案
- 2025年保安證考試結(jié)果分析試題及答案
- 經(jīng)典保安證考試試題及答案總結(jié)
- 全面準(zhǔn)備保安證考試試題及答案
- 保安證考前必看試題及答案
- 網(wǎng)絡(luò)教育學(xué)習(xí)平臺(tái)
- 保安證考試內(nèi)容詳解試題及答案
- 語(yǔ)文學(xué)習(xí)任務(wù)群解讀
- 2024春蘇教版《亮點(diǎn)給力大試卷》數(shù)學(xué)六年級(jí)下冊(cè)(全冊(cè)有答案)
- 中國(guó)短暫性腦缺血發(fā)作早期診治指導(dǎo)規(guī)范
- 《知識(shí)產(chǎn)權(quán)執(zhí)法》課件
- 成人重癥患者鎮(zhèn)痛管理(專家共識(shí))
- 某三甲醫(yī)院物業(yè)管理整體策劃及管理思路方案全套
- 2022年新高考遼寧歷史高考真題含解析
- GB/T 42765-2023保安服務(wù)管理體系要求及使用指南
- 澳大利亞11天自由行行程單英文版
- 員工守則十條
- 【中國(guó)民航安檢的發(fā)展現(xiàn)狀及發(fā)展建議4000字(論文)】
評(píng)論
0/150
提交評(píng)論