算法設計:數據結構-樹

2020-11-19 大數據和人工智慧交流

一、樹的概念

一個結點有一個前驅和多個後繼結點,這種數據結構是樹形結構

1、樹的定義

樹(Tree)是n個結點的集合,集合中有一個稱為根(root)的特殊節點,在根節點分布著一些互相不相交的集合,每個集合又是一個樹,這些樹稱為根節點的子樹


(1)空集合也是樹

(2)單個結點是一棵樹,樹根就是該結點本身

(3)若某樹有多個結點,則每個節點都可以看成是根結點

(4)在一棵樹中,有且僅有一個結點沒有前驅,這個結點就是根節點

(5)除根結點外,其餘每個結點有且僅有一個前驅,如圖B的前驅為A,不能有其它前驅

(6)每個結點可以有任意多個後繼例如:A有B、C、D三個後繼


2、樹的相關術語

(1)父節點、子節點、兄弟結點

每個節點的子樹的根稱為該結點的兒子(子結點),相應的,該結點被稱為子結點的父親(父節點),具有同一父結點的的結點稱為兄弟結點,例如結點A是B、C、D的父結點,相應的,結點B、C、D就是結點A的子結點,而結點B、C、D之間是兄弟結點。對這種層次關係進行擴展,可得出祖先結點和子孫結點等關係


(2)結點的度

一個結點的子樹的數量稱為該結點的 "度"。例如:結點A有3個子樹,因此結點A的"度"是3;而結點B、C、D的"度"分別為1、2、2


(3)樹的度

一棵樹的度是指該樹中結點的最大度數,上圖樹的度為3(結點A的度為3)

4)葉結點和分支結點

樹中度為零的結點稱為葉節點或終端節點。樹中度不為零的結點稱為分支結點或非終端節點。節點E、J、K、L、M、N為葉節點

(5)節點的層數

樹是一種層次結構,每個節點都是處在一定的層次上

(6)樹的深度

一棵樹中節點的最大層數稱為樹的深度。例如,圖中所示的樹的深度為4

(7)有序樹和無序樹

若樹中各節點的子樹(兄弟節點)是按一定次序從左向右安排的,稱為有序樹,否則稱為無序樹

(8)森林

森林是m(m>=0)課互不相交的樹的集合。如果刪去圖中所示樹的根節點A,留下的3棵子樹就構成了一個森林

3、樹的表示

樹的表示方法很多,常用的方法是用括號:先將根節點放入一對圓括號中,然後把它的子樹由左至右的順序放入括號中,而對子樹也採用同樣的方法處理;同層子樹與它的根節點用圓括號括起來,同層子樹之間用逗號隔開,最後用閉括號括起來

( A( B(E) ) ,(C(F(J)),(G (K,L))),(D(H),(I(M,N))))

二、二叉樹的概念

在樹的應用中,二叉樹特別重要,這是因為處理樹的許多算法應用到二叉樹時變得非常簡單,而任意的樹又可以方便的轉換為對應的二叉樹。因此,只需要定義二叉樹的算法,然後將其它樹轉換為二叉樹,即可方便的對所有樹進行操作

1、二叉樹的定義

一個二叉樹是n個結點的集合,此集合要麼是空集,要麼是由一個根節點加上分別稱為左子樹和右子樹的兩個互不相交的二叉樹

二叉樹任意節點最多只能有兩個子節點;如果只有一個子節點,可以是左子樹也可以是右子樹。因此,二叉樹有5種基本形態:

(1)空

沒有任何節點

(2)僅有根節點

只有根節點,沒有子節點

(3)僅有左子樹

(4)僅有右子樹

(5)左右子樹都有


2、二叉樹和樹的兩個主要差別如下:

(1)樹中節點的最大度數沒有限制,而二叉樹節點的最大度數為2

(2)樹的節點無左右之分,而二叉樹的節點有左右之分,因為二叉樹有左右之分,所以二叉樹是有序樹

3、特殊的二叉樹

(1)滿二叉樹

在二叉樹中,除最下一層的葉子節點外,每層的節點都有2個子節點,就構成了滿二叉樹


(2)完全二叉樹

除二叉樹最後一層外,其它各層的節點數都達到最大個數,且最後一層從左向右的葉節點連續存在,只缺右側若干節點,就是完全二叉樹


4、二叉樹的性質

(1)在二叉樹中,第i層的節點總數最多為


(2)深度為k的二叉樹最多有

個節點(k>=1)


(3)對於一個二叉樹,如果其葉節點數為n0,而度為2的節點總數為n2,則n0=n2+1


(4)具有n個節點的完全二叉樹的深度k為:k = [log2n ] + 1


(5)有n個節點的完全二叉樹各節點如果用順序方式存儲,對任意節點i,有如下關係:

如果i!=1,則其父節點的編號為i/2

如果2*i<=n,則其左子樹根節點編號為2*i;若2*I > n,則無左子樹

如果2*i + 1 <=n,則其右子樹根節點編號為2*i + 1;若2*i +1 > n,則無右子樹

三、二叉樹的存儲

二叉樹通常可採用順序存儲結構和鏈式存儲結構

1、順序存儲結構

與線性表的順序存儲類似,二叉樹的順序存儲結構一般也由一個一維數組來構成,二叉樹上的節點按某種規定的次序逐個保存到數組的各個單元中

二叉樹順序存儲結構的數據定義如下:

#define MAXSIZE 100 //最大節點數

typedef int DATA ; //元素類型

typedef DATA seqBinTree[MAXSIZE ];

seqBinTree SBT; //定義保存二叉樹組

對於一個完全二叉樹,若用順序存儲,各節點之間具有對應關係。如下:



對於一個完全二叉樹,若用順序存儲,各節點之間具有對應關係。例如,對於節點i,其父節點為i/2(若商不整數,則進行取整),而其左子節點的編號為2*i,右子節點的編號為2*i+1

對於節點E,由於存儲在數組第5個位置,可推算出其父節點的序號為5/2 = 2,即其父節點為節點B。而如果節點E有子節點,則其左子節點的序號為2*5 =10,即其左子節點為J。同樣,如果有右子節點,則其右子節點的序號為11,即節點K


如果順序存儲的二叉樹不是完全二叉樹,由於節點和數組中的序號沒了對應關係,就比較麻煩了。為了能使節點與數組序號有對應關係,一般採用的方法是;將非完全二叉樹轉換為完全二叉樹,將左側缺少的節點虛設為無數據的節點(這裡用「#」)


將此圖所示的完全二叉樹按順序保存到一維數組中,得到下圖所示:


但是,保存A---H共7個節點佔用15個存儲空間,造成存儲空間的浪費。因此,對於二叉樹的順序存儲,一般是適用於一些特殊情況(如保存完全二叉樹)


2、鏈式存儲結構

由於二叉樹的順序存儲結構會造成空間浪費,因此,大多數情況下,二叉樹都採用鏈式存儲結構。使用鏈式存儲結構非常符合二叉樹的邏輯結構,一個節點可以由節點元素和兩個分別指向左、右子樹的指針組成


四、操作二叉樹

1、定義二叉樹鏈式結構

#include <stdio.h>

#include <stdlib.h>

#define QUEUE_MAXSIZE 50;//隊列大小

typedef char DATA

typedef struct chainTree{

DATA data; //元素數據

struct chainTree *left;//左子樹指針

struct chainTree *right;//右子樹指針

} chainBinTree;


2、初始化二叉樹

chainBinTree * binTreeInit(chainBinTree * node){//初始化二叉樹根節點

if(node ! = NULL)

{

return node;

}else{

return NULL;

}


}

3、添加節點到二叉樹

bt 為父節點,node為子節點,n=1表示添加左子樹,n=2表示添加右子樹

int binTreeAddNode(chainBinTree *bt,chainBinTre *node,int n)

{

if(bt == NULL){

printf("父節點不存在,請先設置父節點!\n");

return 0;

}

switch(n){

case 1:

if(bt->left)//左子樹不為空

{

printf("左子樹不能為空");

return 0;

}else{

bt->left = node;

}

break;

case 2:

if(bt->right)//右子樹不為空

{

printf("右子樹不能為空");

return 0;

}else{

bt->right = node;

}

break;

default:

printf("參數錯誤");

return 0;

}

return 1;

}

4、獲取二叉樹左右的子樹

chainBinTree *binTreeLeft(chainBinTree *bt)

{

if(bt){

return bt->left;

}else{

return NULL;

}

}


chainBinTree *binTreeRight(chainBinTree *bt)

{

if(bt){

return bt->right;

}else{

return NULL;

}

}

5、獲取二叉樹狀態

檢查二叉樹是否為空

int binTreeIsEmpty(chainBinTree *bt){

if(bt)

return 0;

else

return 1;

}

求二叉樹的深度

int binTreeDeph(chainBinTree *bt){

int dep1,dep2;

if(bt==NULL){

return 0;//空樹深度為0

}else{

//左子樹深度(遞歸調用)

dep1 = binTreeDeph(bt->left)

//右子樹深度(遞歸調用)

dep2 = binTreeDeph(bt->right)

if(dep1 > dep2){

return dep1 + 1;

}else{


return dep2 + 1;

}

}

}

6、在二叉樹中查找

chainBinTree *binTreeFind(chainBinTree *bt,DATA data){

chainBinTree *p;

if(bt == NULL){

return NULL;

}else{

if(b->data == data){

return bt;

}else{

if(p = binTreeFind(bt->left,data))

return p;

else if(p = binTreeFind(bt->right,data))

return p;

else

return NULL;

}

}

}

該函數有2個參數,bt是需要查找的二叉樹的根節點,data為需要查找的節點數據

7、清空二叉樹

在向二叉樹添加節點時,每個節點都由malloc函數申請分配內存,因此需要清空二叉樹則必須使用free函數來釋放節點所佔的內存。清空二叉樹的操作就是通過遞歸調用,對二叉樹進行遍歷,釋放各個節點所佔的內存

105 void binTreeClear(chainBinTree *bt)

106 {

107 if(bt)

108 {

109 binTreeClear(bt->left);//清空左子樹

110 binTreeClear(bt->right);//清空了右子樹

111 free(bt);//釋放當前節點所佔內存

112 bt = NULL;

113 }

114 return;

115 }

該函數有一個參數bt,就是需要清空二叉樹的根節點。第107行進行判斷,若當前節點bt不為空(表示還佔用了系統內存),這時,不能直接使用free釋放當前節點所佔內存,因為該節點還可能有子樹,如果直接將該節點所佔內存釋放,則無法再連結到其左右子樹,造成內存被無效佔用。因此,這裡首先需要執行第109、110行遞歸調用當前函數,用來清空當前節點的左子樹和右子樹,最後在執行第111行釋放當前節點所佔內存

五、遍歷二叉樹

由於二叉樹是非線性結構,那麼將數據按二叉樹結構保存時,怎樣才能在所有節點中查找所需要的數據呢?這就需要定義一種算法,將二叉樹的各個節點轉換成一個線性序列來表示,以方便對各節點數據的檢索,這就是二叉樹的遍歷

遍歷是對樹的一種最基本的運算,所謂遍歷二叉樹,就是按一定的規則和順序走遍二叉樹的所有節點,使每一個節點都被訪問一次,而且只能被訪問一次

如下圖所示具有左右子樹的二叉樹,其中D表示根節點,L表示左子樹,R表示右子樹,對其進行遍歷有3種方式:


1、先序遍歷(DLR):稱為先根次序遍歷,即先訪問根節點,再按先序遍歷左子樹,最後按先序遍歷右子樹

2、中序遍歷(LDR):稱為中根次序遍歷,即先按中序遍歷左子樹,再訪問根節點,最後按中序遍歷右子樹

3、後序遍歷(LRD):稱為後根次序遍歷,即先按後序遍歷左子樹,再按後序遍歷右子樹,最後訪問根節點

先序遍歷

1、算法的偽代碼描述

void binTree_DLR(binTree)

{

if(二叉樹不為空)

{

訪問根節點;

binTree_DLR(left); //先序遍歷左子樹

binTree_DLR(right);//先序遍歷右子樹

}

}


2、代碼實現

void preOrder(binTree root){

if(root != NULL ){

printf("%d",root->data);//訪問根結點

preOrder(root->lchild); //先序遍歷根節點的左子樹

preOrder(root->rchild); //先序遍歷根節點的右子樹

}

}

中序遍歷

void inOrder(binTree root){

if(root !=NULL ){

inOrder(root->lchild);//中序遍歷根結點的左子樹

printf("%d",root->data);//訪問根節點

inOrder(root->rchild);//中序遍歷根結點的右子樹

}

}


後序遍歷

void postOrder(binTree root){

if(root !=NULL ){

postOrder (root->lchild);//中序遍歷根結點的左子樹

postOrder (root->rchild);//中序遍歷根結點的右子樹

printf("%d",root->data);//訪問根節點

}

}

遍歷二叉樹的基本操作就是訪問節點,不論按照哪種次序遍歷,對於含有n個節點的二叉樹,遍歷算法的時間複雜度都為O(n)。因為在遍歷的過程中,每進行一次遞歸調用,都將函數的「活動記錄」壓入棧中,因此,棧的最大長度恰為樹的高度。所以,在最壞情況下,二叉樹有n個節點且高度為n的單枝樹,遍歷算法的空間複雜度也為O(n)

藉助一個棧,可將二叉樹的遞歸算法轉換為非遞歸算法。下面給出中序遍歷的非遞歸算法

int inOrderTraverse(binTree root){

initStack(st);//創建個空棧

p = root;//p指向樹根節點

while(p!=NULL || !initStack(st)){

if(p!=NULL){//不是空樹

push(st,p);//根節點指針進棧

p = p->lchild;//進入根的左子樹

}else{

q = top(st); pop(st);//棧頂元素出棧

printf("%d",q->data);//訪問根節點

p = q->rchild;//進入根的右子樹

}

}

}

對於二叉樹,還有層次遍歷。設二叉樹的根節點所在層樹為1,層序遍歷就是從樹的根節點出發,首先訪問第1層的樹根節點,然後從左到右依次訪問第2層上的節點,其次是第3層上的節點,以此類推,自上而下,自左至右逐層訪問樹中各節點的過程就是層序遍歷


上圖中按照層次遍歷的結果為:ABCDEFGHIJKL

//按照層次遍歷

public static void binTree_level(TreeNode root){

int QUEUE_MAXSIZE = 6;

TreeNode p;

TreeNode q[]=new TreeNode[QUEUE_MAXSIZE];//定義個順序隊列

int head = 0;//定義首序號

int tail = 0;//定義尾序號

if(root!=null){

//計算循環隊列隊尾序號

tail = (tail + 1)%QUEUE_MAXSIZE;

q[tail] = root;

}

//隊列不為空,進行循環

while(head!=tail){

//計算循環隊列隊首序號

head = (head + 1)%QUEUE_MAXSIZE;

//獲取隊首元素

p = q[head];

//若節點有左子樹,則左子樹進隊

if(p.left!=null){

tail = (tail+1)%QUEUE_MAXSIZE;

q[tail] = p.left;

}

//若節點有右子樹,則右子樹進隊

if(p.right!=null){

tail = (tail+1)%QUEUE_MAXSIZE;

q[tail] = p.right;

}

}

for(TreeNode obj:q){

if(obj!=null){

System.out.println(obj.value);

}

}


}

六、線索二叉樹

對於二叉樹進行遍歷得到的節點序列,可以將遍歷的結果看成是一個線性表。在該線性表中,除了第1個節點外,每個節點都有(且僅有)一個前驅;除了最後一個節點外,每個節點都有(且僅有)一個後繼。例如:下列二叉樹經過中序遍歷後結果為

B F D A C G E H


線索二叉樹的表示


當以二叉樹鍊表形式來保存二叉樹時,只能找到節點的左右子樹信息,而不能直接得到節點的前驅和後繼(只有通過遍歷,在動態過程中才能查到前驅和後繼的信息)。如果增加前驅和後繼的指針那麼增加了存儲的開銷。其實由二叉樹性質可知,對於一顆具有n個節點的二叉樹,對應的二叉樹鍊表中共有2n個指針域,其中n-1個用於指向除根節點外的n-1個節點,另外n+1個指針域為空。可以利用二叉樹中的這些空指針域來存放節點的前驅和後繼。將每個節點中為空的左指針或右指針分別用於指向節點的前驅和後繼,即可得到線索二叉樹


在一個線索二叉樹中,為了區別每個節點的左、右指針域所存放的是子樹指針,還是線索,必須在節點結構中增加兩個標誌域:一個是左線索標誌域lflag,另一個是右線索標誌域eflag。若某個標誌為1,則表示對應的指針域為線索,否則,對應的指針域為子樹指針

七、哈夫曼樹

1. 哈夫曼樹的構造

給定N個權值分別為w1, w2, ..., Wn的節點。構造哈夫曼樹的算法描述如下:

1)將這N個結點分別作為N棵樹僅含一個結點的二叉樹,構成森林F

2)構造一個新節點,並從F中選取兩棵根結點權值最小的樹作為新節點的左、右子樹, 並且將新節點的權值置為左、右子樹上根結點的權

值之和

3)從F中刪除剛才選出的兩棵樹,同時將新得到的樹加入F中

4)重複步驟2和3,直至F中只剩下一棵樹為止

2. 哈夫曼編碼

哈夫曼編碼是一種被廣泛應用而且非常有效的數據壓縮編碼,它是可變長度編碼。可變長編碼即可以對待處理字符串中不同字符使用不等長的二進位位表示,可變長編碼比固定長度編碼好很多,可以對頻率高的字符賦予短編碼,而對頻率較低的字符則賦予較長一些的編碼,從而可以使平均編碼長度減短,起到壓縮數據的效果。

哈夫曼編碼是前綴編碼。如果沒有一個編碼是另一個編碼的前綴,則稱這樣的編碼為前綴編碼。對前綴編碼的解碼也是相對簡單的,因為沒有一個碼是另一個編碼的前綴,所以可以識別出第一個編碼,將它翻譯為原碼,再對餘下的編碼文件重複同樣操作。

哈夫曼編碼首先要構造一棵哈夫曼樹,首先,將每個出現的字符當做一個獨立的結點,其權值作為它出現的頻度(或次數),然後構造哈夫曼樹。顯然所有字符節點均出現在葉子結點中。我們可以將字符的編碼解釋為從根至該字符路徑上標記的序列,其中標記為0表示"轉向左孩子",標記為1表示為"轉向右孩子"。 如下圖,矩形方塊表示字符及出現的次數


因此,這棵哈夫曼樹的WPL為:

WPL = 1*45 + 3 * (13+12+16) + 4 * (5+9) = 224

哈夫曼樹練習

1、設哈夫曼樹中的節點總數為49,若用二叉鍊表作為存儲結構,則該哈夫曼樹中總共有個空指針域?


2、對於n(n大於等於2)個權值均不相同的字符構成哈夫曼樹,以下敘述正確的是()


A、樹中一定沒有度為1的節點

B、該樹一定是一顆完全二叉樹

C、樹中任一非葉節點的權值一定不小於子孫中任一節點的權值

D、樹中兩個權值最小的節點一定是兄弟節點(假設這兩個節點恰好有兩個)


3、若以(4、5、6、7、8)作為葉節點的權值構造哈夫曼樹,則其帶權路徑長度是多少?


4、某段文本中各個字母出現的頻率是a為4、b為3、o為12、h為7,i為10,使用哈夫曼編碼,則可能的編碼是

A、 a(001) 、b(000)、h(01)、i(10)、o(11)

B、 a(000) 、b(0001)、h(001)、o(01)、i(1)

C、 a(000) 、b(001)、h(01)、i(10)、o(00)

D、 a(0000) 、b(0001)、h(001)、o(000)、i(1)

5、用二進位來編碼字符串「xyzwxyxx」,需要能夠根據編碼解碼回原來的字符串,則最少需要()長度的二進位字符串

A、12 B、14 C、15 D、18 E、24

相關焦點

  • 算法數據結構—樹
    樹今天我們會介紹樹這種數據結構,樹作為數據存儲的一種結構,相對於棧、隊列和表要相對複雜一些。也是一種常見的數據結構,例如我們文件在計算機中就是以樹的結構進行存儲的。組織架構不過在計算機中重點研究的就是二叉樹,不過我們還是先從樹開始介紹,首先我們應該知道樹是一種非線性的數據結構
  • 「算法與數據結構」二叉樹之美
    樹是用來模擬具有樹狀結構性質的數據集合。或者你可以把它認為是一種「抽象數據結構」或是實現這種抽象數據類型的數據結構,用來模擬具有樹狀結構性質的數據集合。如它名字所描述的那樣,二叉樹是每個節點最多有兩個子樹的樹結構,通常子樹被稱作「左子樹」和「右子樹」。
  • 數據結構與算法——最小生成樹
    而在實際生活中的許多問題都是通過轉化為圖的這類數據結構來求解的,這就涉及到了許多圖的算法研究。例如:在 n 個城市之間鋪設光纜,以保證這 n 個城市中的任意兩個城市之間都可以通信。由於鋪設光纜的價格很高,且各個城市之間的距離不同,這就使得在各個城市之間鋪設光纜的價格不同。那麼如何選擇鋪設線路的方案,才能使費用最低呢?
  • 數據結構與算法之算法概述
    二、什麼是數據結構數據結構,對應的英文單詞是data structure,是數據的組織、管理和存儲格式,其使用目的是為了高效地訪問和修改數據。線性結構線性結構是最簡單的數據結構,包括數組、鍊表,以及由它們衍生出來的棧、隊列、哈希表。2.樹樹是相對複雜的數據結構,其中比較有代表性的是二叉樹,由它又衍生出了二叉堆之類的數據結構。3.圖圖是更為複雜的數據結構,因為在圖中會呈現出多對多的關聯關係。
  • 快速入門數據結構和算法
    常見的排序算法是如何實現的?各有什麼優缺點?本文簡要分享算法基礎、常見的數據結構以及排序算法,給同學們帶來一堂數據結構和算法的基礎課。了解常見數據結構和算法,溝通沒有障礙。活學活用:遇到問題時知道要用什麼數據結構和算法去優化。
  • 數據結構與算法——紅黑樹
    前面我們提到了二叉查找樹,支持快速的查找、插入和刪除操作。中序遍歷二叉查找樹,可以輸出有序的數據序列,非常高效。根節點是黑色節點是紅色或黑色所有葉子節點都是黑色,葉子節點為 NIL 節點,不儲存數據結果是這個樹大致上是平衡的。因為操作比如插入、刪除和查找某個值的最壞情況時間都要求與樹的高度成比例,這個在高度上的理論上限允許紅黑樹在最壞情況下都是高效的。紅黑樹相對於AVL樹來說,犧牲了部分平衡性以換取插入/刪除操作時少量的旋轉操作,整體來說性能要優於AVL樹。
  • 數據結構和算法對python意味著什麼?
    數據結構和算法對於python而言是他的靈魂;程序是數據結構加上算法來實現的,對於任何一門程式語言都離不開數據結構和算法,但是對於python而言內置了基礎的數據結構如列表、字典、集合等,再加上眾多包,所以弱化了數據結構和算法的使用。
  • 如何提升數據結構方面的算法能力
    那麼怎麼提升數據結構方面的算法能力呢?我認為主要是從基礎和應用這兩方面著手。因為算法是基於某種選擇的數據結構的。對於算法的時間複雜度和空間複雜的的理解和計算,對於常見算法的掌握。,如何提高算法能力就涉及如何將數據結構和算法應用於特定的場景,以及在實際使用中該如何選擇對應算法。
  • 分享給 .NET 開發者的一本數據結構與算法入門書
    不管是為了面試還是為了提高編程技能,作為一名優秀的開發者,都應該對數據結構和算法有基本的了解。有很多關於學習數據結構和算法的書,但基本上都是基於 C/C++語言或 Java 語言的,基於 C 語言的電子書:《數據結構與算法:C語言實現的數據結構和算法。
  • JAVA必須掌握的數據結構和算法
    常見的數據結構鍊表LinkedHashSet LinkedList 底層數據結構由鍊表和哈希表組成。數據的添加和刪除都較為方便,就是訪問比較耗費時間。數組ArrayList 訪問數據十分簡單,而添加和刪除數據比較耗工夫堆堆是一種圖的樹形結構,被用於實現「優先隊列",優先隊列是一種數據結構,可以自由添加數據,但取出數據時要從最小值開始按順序取出
  • 數據結構圖的最小生成樹的算法和應用舉例
    一、最小生成樹介紹圖結構是一種非常重要的非線性數據結構,帶權圖的最小生成樹在工程技術,科學管理的最優解問題中有著廣泛的應用。最小生成樹:權值和最小的生成樹最小生成樹的性質:假設G=(V,E)是個連通圖,U是頂點V的一個非空子集。
  • 大廠面試系列(七):數據結構與算法等
    數據結構和算法鍊表鍊表,常見的面試題有寫一個鍊表中刪除一個節點的算法、單鍊表倒轉、兩個鍊表找相交的部分,這個一般必須得完全無誤的情況下寫出來;給出兩個鍊表的頭結點,找出這兩個鍊表的交點。你這個算法的時間複雜度是多少數組A,2*n個元素,n個奇數、n個偶數,設計一個算法,使得數組奇數下標位置放置的都是奇數,偶數下標位置放置的都是偶數 •先說下你的思路 •下一個奇數?怎麼找? •有思路麼? •你這樣時間複雜度有點高,如果要求O(N)要怎麼做手寫算法,兩個有序數組的合併。
  • 數據結構與算法分析筆記——B樹
    數據結構與算法分析筆記——B樹B樹AVL樹的特徵是,通過在插入或刪除時的微調,使得整個樹中任意節點的左子樹和右子樹之間的高度差不超過1。這樣的結果是,整棵樹的高度不至於太高。那麼,如果我們想要得到一棵更低的樹?該如何呢?
  • 數據結構基礎:樹結構的學習筆記
    樹的高度:一棵樹的最大層次數稱為樹的高度或者樹的深度。有序(無序)樹:樹中的節點的各個子樹看成是從左到右有次序的,即不能交換,則稱為有序樹,否則為無序樹。森林:m(m>=0)棵互不相交的樹的集合。
  • 數據結構之樹和二叉樹
    01樹在計算機科學中,樹(英語:tree)是一種抽象數據類型(ADT)或是實現這種抽象數據類型的數據結構,用來模擬具有樹狀結構性質的數據集合結點不僅包含數據元素,而且包含指向子樹的分支。以上圖所示,6結點不僅包含數據元素6,還包含3個指向子樹的指針。結點的度:結點擁有的子樹的個數或者分支的個數。例如 6結點有3棵子樹,所以3結點的度為3。
  • 藍盟IT外包,數據結構和算法:圖形結構
    圖表結構是比樹結構更複雜的非線性結構。 在樹結構中,節點之間有分支層次關係,各層次上的節點只與一個層次上的多個節點相關,但有可能只與下一層次上的多個節點相關。 在圖表結構中,任意兩個節點之間可能存在相關性。 也就是說,節點之間的相鄰關係是任意的。
  • Java數據結構與算法——字符串匹配相關算法
    Java裡用的是indexOf函數,其底層就是字符串匹配算法.其中字符串匹配算法主要包括:1. BF(暴力匹配)算法1.1概念和原理Brute Force叫作暴力匹配算法,也叫樸素匹配算法。其主要實現原理就是 在主串中,檢查起始位置分別是 0、1、2…n-m 且長度為 m 的 n-m+1 個子串,看有沒有跟模式串匹配的。
  • 深入淺出 數據結構和算法(快速入門下篇)
    通過上篇的學習,相信你對數據結構和算法的概念有了基本認知。抽象的理論總要結合實例,才能更好理解和記憶。下篇中,聚焦主要的數據結構和常見的算法,助你快速實現入門。 常見數據結構一、數組數據是有限個相同類型的變量所組成的有序集合。
  • 結構與算法:二叉樹與多叉樹
    一、樹狀結構1、數組與鍊表數組結構數組存儲是通過下標方式訪問元素,查詢速度快,如果數組元素是有序的,還可使用二分查找提高檢索速度;如果添加新元素可能會導致多個下標移動,效率較低;鍊表結構鍊表存儲元素,對於元素添加和刪除效率高
  • 373,數據結構-6,樹
    甚至堆我們也可以把它看成是一棵樹,樹的這麼多種類中,我們最常見的應該是二叉樹了,下面我們來看一下他的結構。哈夫曼樹:帶權路徑最短的二叉樹稱為哈夫曼樹或最優二叉樹;應用:樹的種類實在是太多,關於樹的算法題也是賊多,這一篇文章不可能全部介紹完,我們需要具體問題再具體分析。