C演算法學習筆記(2)-二叉尋找樹

來源:互聯網
上載者:User

本文原始地址:C演算法學習筆記(2)-二叉尋找樹

尋找操作

若根結點的關鍵字值等於尋找的關鍵字,成功。
否則,若小於根結點的關鍵字值,遞迴查左子樹。
若大於根結點的關鍵字值,遞迴查右子樹。
若子樹為空白,尋找不成功。

 

/* //二叉樹尋找演算法 //T 二叉樹 //x 要尋找的值 */BiTree BSTSearch(BiTree T,int x){    BiTreeNode *p;    if (T != NULL)    {        p = T;        while (p != NULL)        {            if (p->data == x)//如果該結點就是我們想要的            {                return p;            }else if(x > p->data)//如果尋找的值是該結點右子樹            {                p = p->rchild;            }else//如果尋找的值是該結點左子樹            {                p = p->lchild;            }        }    }    return NULL;}

 

 

插入操作

首先執行尋找演算法,找出被插結點的父親結點。
判斷被插結點是其父親結點的左、右兒子。將被插結點作為葉子結點插入。
若二叉樹為空白。則首先單獨產生根結點。
注意:新插入的結點總是葉子結點。

 

/* //二叉樹插入操作 //T 二叉樹 //x 要插入的值 */int BSTInsert(BiTree *T,int x){    BiTreeNode *p = NULL;//把x組裝成一個只有根結點的樹    BiTreeNode *cur = NULL;//紀錄當前遍曆的結點    BiTreeNode *parent = NULL;//紀錄上一次遍曆的結點,最後一個值為我們需要插入的結點位置    cur = *T;    while (cur != NULL)    {        if (cur->data == x)//插入操作如果數值已存在,插入失敗        {            return 0;        }        parent = cur;//將到該結點子樹遍曆,紀錄下該結點,該迴圈最終輸出值        if (x < cur->data)//到該結點左子樹繼續遍曆        {            cur = cur->lchild;        }else//到該結點右子樹繼續遍曆        {            cur = cur->rchild;        }    }    //申請記憶體空間    p = (BiTreeNode *)malloc(sizeof(BiTreeNode));    if (!p)//記憶體空間申請失敗,記憶體不夠用了,終止程式    {        exit(-1);    }    //初始化p結點    p->data = x;    p->lchild = NULL;    p->rchild = NULL;        if (!parent)    {        *T = p;//這本來就是棵空樹,p將會作為根結點    }else if(x < parent->data)    {        parent->lchild = p;    }else    {        parent->rchild = p;    }    return 1;//插入成功}

 

刪除操作

1.若*p結點為葉子結點,即PL(左子樹)和PR(右子樹)均為空白樹。由於刪去葉子結點不破壞整棵樹的結構,則只需修改其雙親結點的指標即可。
2.若*p結點只有左子樹PL或右子樹PR,此時只要令PL或PR直接成為其雙親結點*f的左子樹(當*p是左子樹)或右子樹(當*p是右子樹)即可,作此修改也不破壞二叉排序樹的特性。
3.若*p結點的左子樹和右子樹均不空。在刪去*p之後,為保持其它元素之間的相對位置不變,可按中序遍曆保持有序進行調整,可以有兩種做法:
其一是令*p的左子樹為*f的左/右(依*p是*f的左子樹還是右子樹而定)子樹,*s為*p左子樹的最右下的結點,而*p的右子樹為*s的右子樹;
其二是令*p的直接前驅(或直接後繼)替代*p,然後再從二叉排序樹中刪去它的直接前驅(或直接後繼)-即讓*f的左子樹(如果有的話)成為*p左子樹的最左下結點(如果有的話),再讓*f成為*p的左右結點的父結點。

 

 

/* //刪除結點 //刪除的結點s //原則:保持二叉樹性質不變-根結點的值大於左子樹的值小於右子樹的值... */void DeleteNode(BiTree *s){    if (!s) return;    BiTreeNode *q = NULL;//中間量,紀錄舊的的s結點資料    BiTreeNode *x = NULL;    BiTreeNode *y = NULL;        if(!(*s)->rchild)//如果右子樹不存在    {        q = (*s);        (*s) = (*s)->lchild;        free(q);    }else if(!(*s)->lchild)//如果左子樹不存在    {        q = (*s);        (*s) = (*s)->rchild;    }else//如果左右都存在的話,令*p的直接前驅(或直接後繼)替代*p,然後再從二叉排序樹中刪去它的直接前驅(或直接後繼)-即讓*f的左子樹(如果有的話)成為*p左子樹的最左下結點(如果有的話),再讓*f成為*p的左右結點的父結點。    {        x = (*s);        y = (*s)->lchild;        while (y->rchild)//尋找s的直接前驅結點,y為s的直接前驅結點,x為y的雙親結點        {            x = y;            y = y->lchild;        }        (*s)->data = y->data;//結點s被y取代        if (x != (*s))//如果結點s的左孩子結點不存在右子樹        {            x->rchild = y->lchild;//使y的左子樹成為x的右子樹        }else        {            x->lchild = y->lchild;        }        free(y);    }}/* //在二叉樹中尋找關鍵字為x的結點,並刪除,刪除成功返回1,否則返回0 //T 二叉樹 //x 關鍵字 */int BSTDelete(BiTree *T,int x){    if (!*T) return 0;    if (x == (*T)->data)    {        DeleteNode(T);    }else if (x < (*T)->data)    {        BSTDelete(&(*T)->lchild,x);    }else    {        BSTDelete(&(*T)->rchild,x);    }    return 1;}

 

附:中序遍曆

 

//中序遍曆void InOrderTraverse(BiTree T){    if (T)    {        InOrderTraverse(T->lchild);        printf("%4d",T->data);        InOrderTraverse(T->rchild);    }}

 

 

視頻地址:BST:二叉尋找樹

關於二叉尋找樹

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.