<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    莊周夢(mèng)蝶

    生活、程序、未來(lái)
       :: 首頁(yè) ::  ::  :: 聚合  :: 管理

    一 樹(shù)、二叉樹(shù)和二叉查找樹(shù)

    1。樹(shù)的概念:

    遞歸定義:

    1) 一個(gè)空結(jié)構(gòu)是一個(gè)空樹(shù)

    2)如果t1,...,tk是分離的樹(shù),那么以t1,...,tk的根為子節(jié)點(diǎn)的根結(jié)構(gòu)也是樹(shù)

    3)只有按照1,2規(guī)則產(chǎn)生的結(jié)構(gòu)才是樹(shù)

    樹(shù)的概念更多用于分層結(jié)構(gòu),比如數(shù)據(jù)庫(kù)管理系統(tǒng)的分層模型。

    2。二叉樹(shù)(binary tree):所有節(jié)點(diǎn)都有兩個(gè)子節(jié)點(diǎn)(可以為空),并且每個(gè)子節(jié)點(diǎn)都指明為左子節(jié)點(diǎn)還是右子節(jié)點(diǎn)

    1)完全二叉數(shù),滿足第i層,有2的i-1次方個(gè)子節(jié)點(diǎn)此條件的二叉樹(shù)

    2)對(duì)于所有非空二叉樹(shù),如果它的中間子節(jié)點(diǎn)恰好有兩個(gè)非空子女,那么葉的數(shù)目m大于中間節(jié)點(diǎn)的數(shù)目k,并且m=k+1

    3。二叉查找樹(shù)(binary search tree)

    1)概念:對(duì)于樹(shù)中的每個(gè)節(jié)點(diǎn)n,其左子節(jié)點(diǎn)中保存的所有數(shù)值都小于n保存的數(shù)值,右子節(jié)點(diǎn)保存的數(shù)值都大于n保存的數(shù)值。

    2)二叉查找樹(shù)可以實(shí)現(xiàn)更為優(yōu)越的查找性能,主要實(shí)現(xiàn)方式有數(shù)組和鏈表結(jié)構(gòu),相比較而言,鏈表實(shí)現(xiàn)更為容易,因?yàn)閿?shù)組實(shí)現(xiàn)刪除和添加功能需要移動(dòng)數(shù)組元素(如填補(bǔ)刪除空位等)

    ?

    二。二叉樹(shù)的實(shí)現(xiàn)

    首先設(shè)計(jì)一個(gè)節(jié)點(diǎn)(設(shè)計(jì)一個(gè)整型的二叉樹(shù),通用型通理):

    此類簡(jiǎn)單明了,一個(gè)信息值,兩個(gè)引用(左右子樹(shù))。

    public ? class ?IntBSTNode? {
    ?
    protected ? int ?key;

    ?
    protected ?IntBSTNode?left,?right;

    ?
    public ?IntBSTNode()? {
    ??left?
    = ?right? = ? null ;
    ?}


    ?
    public ?IntBSTNode( int ?el)? {
    ??
    this (el,? null ,? null );
    ?}


    ?
    public ?IntBSTNode( int ?el,?IntBSTNode?left,?IntBSTNode?right)? {
    ??key?
    = ?el;
    ??left?
    = ?left;
    ??right?
    = ?right;
    ?}

    }



    由此類而實(shí)現(xiàn)一個(gè)完整二叉搜索樹(shù):

    public ? class ?IntBST? {
    ?
    protected ?IntBSTNode?root;

    ?
    protected ? void ?visit(IntBSTNode?p)? {
    ??System.out.print(p.key?
    + ? " ? " );
    ?}


    ?
    public ?IntBST()? {
    ??root?
    = ? null ;
    ?}



    第一步,實(shí)現(xiàn)二叉樹(shù)的搜索,查找過(guò)程簡(jiǎn)單明了,對(duì)每一個(gè)節(jié)點(diǎn)將要查找的鍵與當(dāng)前節(jié)點(diǎn)的數(shù)值比較,如果鍵小于該數(shù),就進(jìn)入節(jié)點(diǎn)的左子樹(shù)繼續(xù)比較,反之進(jìn)入右子樹(shù)繼續(xù)此比較過(guò)程。

    ?

    public ?IntBSTNode?search( int ?el)? {
    ??
    return ?search(root,?el);
    ?}


    ?
    protected ?IntBSTNode?search(IntBSTNode?p,? int ?el)? {
    ??
    while ?(p? != ? null )
    ???
    if ?(el? == ?p.key)
    ????
    return ?p;
    ???
    else ? if ?(el? < ?p.key)
    ????p?
    = ?p.left;
    ???
    else
    ????p?
    = ?p.right;
    ??
    return ? null ;
    ?}


    此查找過(guò)程最壞情況,樹(shù)成為鏈表O(n)=(n-1)/2,最好情況:O(n)=lg(n+1)-2。經(jīng)過(guò)計(jì)算可知,一般樹(shù)的平均比較次數(shù)更接近于最好情況。

    第二步,實(shí)現(xiàn)二叉樹(shù)的遍歷,樹(shù)的遍歷就是訪問(wèn)樹(shù)的所有節(jié)點(diǎn),且每個(gè)節(jié)點(diǎn)被訪問(wèn)一次。N個(gè)節(jié)點(diǎn)的樹(shù)有N!種不同的遍歷。我們只考慮兩種情況的遍歷

    1)廣度優(yōu)先遍歷,是從最底層(或最高層)開(kāi)始逐層向上(或向下),而在同層自左向右(或者相反)訪問(wèn)每一個(gè)子節(jié)點(diǎn),因此共有四種情況。考慮自頂向下,自左向右的情況,利用隊(duì)列實(shí)現(xiàn)如下:

    ?

    public ? void ?breadthFirst()? {
    ??IntBSTNode?p?
    = ?root;
    ??Queue?queue?
    = ? new ?Queue();
    ??
    if ?(p? != ? null )? {
    ???queue.enqueue(p);
    ???
    while ?( ! queue.isEmpty())? {
    ????p?
    = ?(IntBSTNode)?queue.dequeue();
    ????visit(p);
    ????
    if ?(p.left? != ? null )
    ?????queue.enqueue(p.left);
    ????
    if ?(p.right? != ? null )
    ?????queue.enqueue(p.right);
    ???}

    ??}

    ?}

    ?

    2) 深度優(yōu)先遍歷,此種遍歷關(guān)心3個(gè)任務(wù):

    V——訪問(wèn)一個(gè)節(jié)點(diǎn)

    L——遍歷左子樹(shù)

    R——遍歷右子樹(shù)

    因此有3!=6種此類遍歷,我們關(guān)心其中3種:

    VLR——先序遍歷樹(shù)

    LVR——中序遍歷樹(shù)

    LRV——后序遍歷樹(shù)

    如果用遞歸來(lái)實(shí)現(xiàn)這3種遍歷非常容易理解,如下:

    public ? void ?preorder()? {
    ??preorder(root);
    ?}


    // 先序

    protected ? void ?preorder(IntBSTNode?p)? {
    ??
    if ?(p? != ? null )? {
    ???visit(p);
    ???preorder(p.left);
    ???preorder(p.right);
    ??}

    ?}


    ?
    public ? void ?inorder()? {
    ??inorder(root);
    ?}


    // 中序

    protected ? void ?inorder(IntBSTNode?p)? {
    ??
    if ?(p? != ? null )? {
    ???inorder(p.left);
    ???visit(p);
    ???inorder(p.right);
    ??}

    ?}


    ?
    public ? void ?postorder()? {
    ??postorder(root);
    ?}


    // 后序

    protected ? void ?postorder(IntBSTNode?p)? {
    ??
    if ?(p? != ? null )? {
    ???postorder(p.left);
    ???postorder(p.right);
    ???visit(p);
    ??}

    ?}



    同樣,我們知道,遞歸調(diào)用總可以被迭代方式取代,只不過(guò)不是這么容易理解了,在此不再列出。

    第三步。插入操作,此算法很簡(jiǎn)單,不詳細(xì)講解,簡(jiǎn)單來(lái)講就是找到合適的位置連接即可

    public?void?insert(int?el)?{
    ????????IntBSTNode?p?
    =?root,?prev?=?null;
    ????????
    while?(p?!=?null)?{?//?find?a?place?for?inserting?new?node;
    ????????????prev?=?p;
    ????????????
    if?(p.key?<?el)
    ????????????????p?
    =?p.right;
    ????????????
    else
    ????????????????p?
    =?p.left;
    ????????}

    ????????
    if?(root?==?null)?//?tree?is?empty;
    ????????????root?=?new?IntBSTNode(el);
    ????????
    else?if?(prev.key?<?el)
    ????????????prev.right?
    =?new?IntBSTNode(el);
    ????????
    else
    ????????????prev.left?
    =?new?IntBSTNode(el);
    ????}


    ???
    第四步。節(jié)點(diǎn)的刪除。
    1)歸并刪除法,當(dāng)被刪除節(jié)點(diǎn)沒(méi)有或者只有一個(gè)子樹(shù)的時(shí)候很簡(jiǎn)單,當(dāng)有兩個(gè)子樹(shù)存在的時(shí)候,情況稍微復(fù)雜。歸并刪除法就是將節(jié)點(diǎn)的兩棵子樹(shù)合并成一棵樹(shù),然后連接到節(jié)點(diǎn)的父節(jié)點(diǎn)上。歸并子樹(shù)的原則,尋找左子樹(shù)中key最大的節(jié)點(diǎn),并將其作為右子樹(shù)的父節(jié)點(diǎn)。相反,也可以尋找右子樹(shù)的key最小的節(jié)點(diǎn),作為左子樹(shù)的父節(jié)點(diǎn)。我們以第一種情況為例:

    public?void?deleteByMerging(int?el)?{
    ????????IntBSTNode?tmp,?node,?p?
    =?root,?prev?=?null;
    ????????
    while?(p?!=?null?&&?p.key?!=?el)?{?//?find?the?node?p
    ????????????prev?=?p;?//?with?element?el;
    ????????????if?(p.key?<?el)
    ????????????????p?
    =?p.right;
    ????????????
    else
    ????????????????p?
    =?p.left;
    ????????}

    ????????node?
    =?p;
    ????????
    if?(p?!=?null?&&?p.key?==?el)?{
    ????????????
    if?(node.right?==?null)?//?node?has?no?right?child:?its?left
    ????????????????node?=?node.left;?//?child?(if?any)?is?attached?to?its?parent;
    ????????????else?if?(node.left?==?null)?//?node?has?no?left?child:?its?right
    ????????????????node?=?node.right;?//?child?is?attached?to?its?parent;
    ????????????else?{?//?be?ready?for?merging?subtrees;
    ????????????????tmp?=?node.left;?//?1.?move?left
    ????????????????while?(tmp.right?!=?null)
    ????????????????????
    //?2.?and?then?right?as?far?as
    ????????????????????tmp?=?tmp.right;?//?possible;
    ????????????????tmp.right?=?//?3.?establish?the?link?between?the
    ????????????????node.right;?//?the?rightmost?node?of?the?left
    ????????????????
    //?subtree?and?the?right?subtree;
    ????????????????node?=?node.left;?//?4.
    ????????????}

    ????????????
    if?(p?==?root)
    ????????????????root?
    =?node;
    ????????????
    else?if?(prev.left?==?p)
    ????????????????prev.left?
    =?node;
    ????????????
    else
    ????????????????prev.right?
    =?node;
    ????????}
    ?else?if?(root?!=?null)
    ????????????System.out.println(
    "key?"?+?el?+?"?is?not?in?the?tree");
    ????????
    else
    ????????????System.out.println(
    "the?tree?is?empty");
    ????}



    2)復(fù)制刪除法:歸并刪除法帶來(lái)的問(wèn)題是可能改變樹(shù)的高度。另一種刪除法也就是復(fù)制刪除法,將待刪除節(jié)點(diǎn)的key用它的前驅(qū)節(jié)點(diǎn)的key來(lái)代替,某一節(jié)點(diǎn)的前驅(qū)節(jié)點(diǎn)就是該節(jié)點(diǎn)左子樹(shù)中key最大的節(jié)點(diǎn)。如下實(shí)現(xiàn):
    ???
    ?public?void?deleteByCopying(int?el)?{
    ????????IntBSTNode?node,?p?
    =?root,?prev?=?null;
    ????????
    while?(p?!=?null?&&?p.key?!=?el)?{?//?find?the?node?p
    ????????????prev?=?p;?//?with?element?el;
    ????????????if?(p.key?<?el)
    ????????????????p?
    =?p.right;
    ????????????
    else
    ????????????????p?
    =?p.left;
    ????????}

    ????????node?
    =?p;
    ????????
    if?(p?!=?null?&&?p.key?==?el)?{
    ????????????
    if?(node.right?==?null)?//?node?has?no?right?child;
    ????????????????node?=?node.left;
    ????????????
    else?if?(node.left?==?null)?//?no?left?child?for?node;
    ????????????????node?=?node.right;
    ????????????
    else?{
    ????????????????IntBSTNode?tmp?
    =?node.left;?//?node?has?both?children;
    ????????????????IntBSTNode?previous?=?node;?//?1.
    ????????????????while?(tmp.right?!=?null)?{?//?2.?find?the?rightmost
    ????????????????????previous?=?tmp;?//?position?in?the
    ????????????????????tmp?=?tmp.right;?//?left?subtree?of?node;
    ????????????????}

    ????????????????node.key?
    =?tmp.key;?//?3.?overwrite?the?reference
    ????????????????if?(previous?==?node)?//?of?the?key?being?deleted;
    ????????????????????previous.left?=?tmp.left;?//?4.
    ????????????????else
    ????????????????????previous.right?
    =?tmp.left;?//?5.
    ????????????}

    ????????????
    if?(p?==?root)
    ????????????????root?
    =?node;
    ????????????
    else?if?(prev.left?==?p)
    ????????????????prev.left?
    =?node;
    ????????????
    else
    ????????????????prev.right?
    =?node;
    ????????}
    ?else?if?(root?!=?null)
    ????????????System.out.println(
    "key?"?+?el?+?"?is?not?in?the?tree");
    ????????
    else
    ????????????System.out.println(
    "the?tree?is?empty");
    ????}


    4。樹(shù)的平衡:如果樹(shù)中任何節(jié)點(diǎn)的兩個(gè)子樹(shù)的高度差或者是0或者為1,那么這樣的二叉樹(shù)就是高度平衡的。如何平衡一棵樹(shù)?
    1)簡(jiǎn)單算法:將樹(shù)中的所有數(shù)據(jù)中序遍歷,放進(jìn)一個(gè)數(shù)組,此數(shù)組已經(jīng)排序,然后折半插入
    ?public?void?balance(int?data[],?int?first,?int?last)?{
    ????????
    if?(first?<=?last)?{
    ????????????
    int?middle?=?(first?+?last)?/?2;
    ????????????System.out.print(data[middle]?
    +?"?");
    ????????????insert(data[middle]);
    ????????????balance(data,?first,?middle?
    -?1);
    ????????????balance(data,?middle?
    +?1,?last);
    ????????}

    ????}

    ???
    2)DSW算法:
    基本原理是通過(guò)樹(shù)的右旋轉(zhuǎn)得到樹(shù)的主干,然后再進(jìn)行左旋轉(zhuǎn)得到平衡樹(shù)
    主站蜘蛛池模板: 九九九精品视频免费| 99在线免费观看| 午夜免费福利视频| 女人与禽交视频免费看| 国产成人A亚洲精V品无码| 亚洲一区二区三区高清视频| 又硬又粗又长又爽免费看 | 中国china体内裑精亚洲日本| 九九全国免费视频| 1000部拍拍拍18免费网站| 亚洲AV成人潮喷综合网| 亚洲精品美女在线观看播放| 青青草国产免费国产是公开| 亚洲免费福利视频| 久久亚洲2019中文字幕| 亚洲熟妇少妇任你躁在线观看| 中文字幕的电影免费网站| 成人免费无码大片A毛片抽搐 | 亚洲日本在线观看视频| 亚洲av成人综合网| a级毛片免费观看视频| 韩国18福利视频免费观看| 老汉色老汉首页a亚洲| 男人j进女人p免费视频| 亚洲精品动漫免费二区| 亚洲AV无码第一区二区三区| 特级毛片A级毛片100免费播放| 久久国产免费福利永久| 亚洲αv久久久噜噜噜噜噜| 边摸边吃奶边做爽免费视频网站 | 亚洲伊人久久综合中文成人网| 亚洲高清一区二区三区| 国产激情免费视频在线观看| 亚洲成?v人片天堂网无码| 亚洲 暴爽 AV人人爽日日碰| 无码免费一区二区三区免费播放| 亚洲午夜爱爱香蕉片| 在线观看亚洲专区| 99精品全国免费观看视频| 在线观看亚洲一区二区| 18禁在线无遮挡免费观看网站|