1. 程式人生 > 實用技巧 >單鏈表結構及連結串列反轉操作java程式碼實現

單鏈表結構及連結串列反轉操作java程式碼實現

資料結構c二叉排序樹基本操作
2020_12_16

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
//二叉排序樹

typedef struct BSTNode {
    int data;
    struct BSTNode *lchild;  //左孩子
    struct BSTNode *rchild;  //右孩子
} BSTNode, *BSTree;

bool Search(BSTree bst, int key, BSTree f, BSTree *p);

void InOderTraverse(BSTree bst)   //中序遞迴遍歷二叉樹
{
    if (bst) {
        InOderTraverse(bst->lchild);
        printf("%d ", bst->data);
        InOderTraverse(bst->rchild);
    }
}

static BSTNode *BuyNode(int data)   //生成一個節點並進行初始化
{
    BSTNode *pTmp = (BSTNode *) malloc(sizeof(BSTNode));
    if (NULL == pTmp) {
        exit(0);
    }
    pTmp->data = data;
    pTmp->lchild = NULL;
    pTmp->rchild = NULL;
    return pTmp;
}

bool Insert(BSTree *bst, int key) {
    if (*bst == NULL) {//空樹
        *bst = BuyNode(key);   //插入根節點
        return true;
    }
    BSTNode *p;
    //先在二叉排序樹中查詢要插入的值是否已經存在
    if (!Search(*bst, key, NULL, &p))  //如果查詢失敗,則插入;此時p指向遍歷的最後一個節點
    {
        BSTNode *pNew = BuyNode(key);
        if (key < p->data) {//將s作為p的左孩子
            p->lchild = pNew;
        } else if (key > p->data) {   //將s作為p的右孩子
            p->rchild = pNew;
        }
        return true;  //插入成功
    } else {
        printf("\nThe node(%d) already exists.\n", key);
    }
    return false;
}

/*
刪除分三種情況:
(1)被刪除的節點無孩子,說明該節點是葉子節點,直接刪
(2)被刪除的節點只有左孩子或者右孩子,直接刪,並將其左孩子或者右孩子放在被刪節點的位置
(3)被刪除的節點既有右孩子又有右孩子
*/

BSTNode *FindParent(BSTree bst, BSTNode *child) {
    if (NULL == bst) {
        return NULL;
    }

    if (bst->lchild == child || bst->rchild == child) {
        return bst;
    } else if (NULL != bst->lchild) {
        return FindParent(bst->lchild, child);
    } else if (NULL != bst->rchild) {
        return FindParent(bst->rchild, child);
    }
    return NULL;
}

void Delete(BSTree *bst, int key) {
    if (NULL == *bst) {
        exit(1);  //空樹直接報錯
    }
//    BSTNode *f = NULL;
    BSTNode *p, *q, *s;
    if (Search(*bst, key, NULL, &p)) //確實存在值為key的節點,則p指向該節點
    {

        if (NULL == p->lchild && p->rchild)  //無左孩子,有右孩子
        {
            q = p->rchild;
            p->data = q->data;    //因為兩個節點之間本質的不同在於資料域的不同,而與放在哪個地址沒有關係
            p->rchild = q->rchild;
            p->lchild = q->lchild;
            free(q);
        } else if (NULL == p->rchild && p->lchild)  //無右孩子,有左孩子
        {
            q = p->lchild;
            p->data = q->data;
            p->rchild = q->rchild;
            p->lchild = q->lchild;
            free(q);
        } else if (p->rchild && p->lchild) //既有左孩子,又有右孩子
        {
            q = p;
            s = p->lchild;   //找左孩子的最右孩子
            while (s->rchild) {
                q = s;
                s = s->rchild;
            }
            p->data = s->data;
            if (q != p) {
                q->rchild = s->lchild;
            } else {
                q->lchild = s->lchild;
            }
            free(s);
        } else {//沒有孩子
            if (*bst == p)   //只有一個根節點
            {
                free(*bst);
                *bst = NULL;
                return;
            }

            BSTNode *parent = FindParent(*bst, p);
            if (parent->lchild == p) {
                parent->lchild = NULL;
            } else {
                parent->rchild = NULL;
            }
            free(p);
        }
    }
}
//查詢成功時,p指向值為key的節點。如果查詢失敗,則p指向遍歷的最後一個節點,f為根節點。
bool Search(BSTree bst, int key, BSTree f, BSTree *p) {
    if (!bst) {
        *p = f;
        return false;
    }
    if (bst->data == key) {//查詢成功,直接返回
        *p = bst;
        return true;
    } else if (bst->data < key) {
        return Search(bst->rchild, key, bst, p);
    }
    return Search(bst->lchild, key, bst, p);
}

int main() {
    freopen("input.txt", "r", stdin);
    printf("請輸入數字個數:\n");
    int n, i;
    scanf("%d", &n);
    BSTNode *root = NULL, *p;
    printf("請輸入要插入的數字:\n");
    for (i = 0; i < n; i++) {
        int x;
        scanf("%d", &x);
        Insert(&root, x);
    }
    InOderTraverse(root);
    printf("請輸入要查詢的數字:\n");
    int x;
    scanf("%d", &x);
    if (Search(root, x, NULL, &p)) printf("存在此數。\n");
    else printf("不存在此數。\n");
//    printf("%d ", Insert(&root, 45));   //輸出0表示插入失敗,輸出1表示插入成功
//    printf("%d\n", Insert(&root, 4));
    printf("請輸入刪除數字個數:\n");
    scanf("%d", &n);
    printf("請輸入要刪除的數字:\n");
    for (i = 0; i < n; i++) {
        int x;
        scanf("%d", &x);
        Delete(&root, x);
    }
    printf("刪除後順序為:\n");
    InOderTraverse(root);
    return 0;
}