1. 程式人生 > >二叉搜尋樹的簡單操作(BST)

二叉搜尋樹的簡單操作(BST)

只寫一個先序遍歷,中序和後序就順序不同


結構體,基本資料型別和兩個指向左右節點的指標

typedef struct TNode * Position;
typedef Position BinTree;
struct TNode {
  int data;
  BinTree left;
  BinTree right;
};



插入

BinTree insert(BinTree BST, int x) {
  if (!BST) {
    BST = (BinTree)malloc(sizeof(struct TNode));  //為空則申請空間
    BST->data = x;
    BST->left = BST->right = NULL;    //將子節點置為空
  } else {
    if (x < BST->data) {
      BST->left = insert(BST->left, x);    //左遞迴
    } else if (x > BST->data){
      BST->right = insert(BST->right, x);
    }
    return BST;
  }
}


最大值

//比BST->data大的都在右子樹,遞迴遍歷
Position findMax(BinTree BST) {
  if (!BST) {
    return NULL;
  } else if (!BST->right) { //右子樹為空
    return BST;
  } else {      
    return findMax(BST->right);
  }
}


最小值

//比BST->data小的都在左子樹,遞迴遍歷
Position findMin(BinTree BST) {
  if (!BST) {
    return NULL;
  } else if (!BST->left) {  //左子樹為空
    return BST;
  } else {    
    return findMin(BST->left);
  }
}


刪除

BinTree deleteValue(BinTree BST, int x) {
  Position pos;
  if (!BST) {
    printf("未找到指定元素\n");
  } else {
    if (x < BST->data) {
      BST->left = deleteValue(BST->left, x);
    } else if (x > BST->data) {
      BST->right = deleteValue(BST->right, x);
    } else {
      if (BST->left && BST->right) {  //存在兩個子節點時
        pos = findMin(BST->right);  //找到右子樹的最小值
        BST->data = pos->data;
        BST->right = deleteValue(BST->right, BST->data);
      } else {      //存在一個子節點或者無子節點的時候
        pos = BST;
        if (!BST->left) {
          BST = BST->right;
        } else {
          BST = BST->left;
        }
        free(pos);
      }
    }
  }
  return BST;
}


查詢特定元素

Position find(BinTree BST, int x) {
  if (!BST) {
    return NULL;
  }

  if (BST->data < x) {      //小於在左,大於在右
    return find(BST->right, x);
  } else if (BST->data > x) {
    return find(BST->left, x);
  } else {
    return BST;
  }
}


具體實現如下

#include<stdio.h>
#include<stdlib.h>

typedef struct TNode * Position;
typedef Position BinTree;
struct TNode {
  int data;
  BinTree left;
  BinTree right;
};

void preOrder(BinTree BST) {
  if (!BST) {
    return ;
  } else {
    printf("%d ", BST->data);   
    preOrder(BST->left);
    preOrder(BST->right);
  }
}

BinTree insert(BinTree BST, int x) {
  if (!BST) {
    BST = (BinTree)malloc(sizeof(struct TNode));  //為空則申請空間
    BST->data = x;
    BST->left = BST->right = NULL;    //將子節點置為空
  } else {
    if (x < BST->data) {
      BST->left = insert(BST->left, x);
    } else if (x > BST->data){
      BST->right = insert(BST->right, x);
    }
    return BST;
  }
}

Position findMin(BinTree BST) {
  if (!BST) {
    return NULL;
  } else if (!BST->left) {
    return BST;
  } else {
    return findMin(BST->left);
  }
}

Position findMax(BinTree BST) {
  if (!BST) {
    return NULL;
  } else if (!BST->right) {
    return BST;
  } else {
    return findMax(BST->right);
  }
}

Position find(BinTree BST, int x) {
  if (!BST) {
    return NULL;
  }

  if (BST->data < x) {      //小於在左,大於在右
    return find(BST->right, x);
  } else if (BST->data > x) {
    return find(BST->left, x);
  } else {
    return BST;
  }
}

BinTree deleteValue(BinTree BST, int x) {
  Position pos;
  if (!BST) {
    printf("未找到指定元素\n");
  } else {
    if (x < BST->data) {
      BST->left = deleteValue(BST->left, x);
    } else if (x > BST->data) {
      BST->right = deleteValue(BST->right, x);
    } else {
      if (BST->left && BST->right) {  //存在兩個子節點時
        pos = findMin(BST->right);  //找到右子樹的最小值
        BST->data = pos->data;
        BST->right = deleteValue(BST->right, BST->data);
      } else {      //存在一個子節點或者無子節點的時候
        pos = BST;
        if (!BST->left) {
          BST = BST->right;
        } else {
          BST = BST->left;
        }
        free(pos);
      }
    }
  }
  return BST;
}

int main(void)
{
  BinTree BST, MinP, MaxP, Tmp;
  int x;
  int N, i, flag;
  BST = NULL;

  printf("輸入初始元素個數:\n");
  scanf("%d", &N);
  printf("輸入各個元素:\n");
  for (int i = 0; i < N; i++) {
    scanf("%d", &x);
    BST = insert(BST, x);
  }

  printf("1.插入元素   2.刪除元素   3.查詢最小值\n");
  printf("4.查詢最大值   5.查詢指定元素   6.先序輸出   7.退出\n");
  while (scanf("%d", &flag) != EOF && flag != 7) {
    switch (flag) {
      case 1: printf("輸入插入元素:\n");scanf("%d", &x);BST = insert(BST, x);break;
      case 2: printf("輸入刪除元素:\n");scanf("%d", &x);BST = deleteValue(BST, x);break;
      case 3: MinP = findMin(BST); printf("最小值為:%d\n\n", MinP->data);break;
      case 4: MaxP = findMax(BST); printf("最大值為:%d\n\n", MaxP->data);break;
      case 5: printf("輸入查詢元素:\n");scanf("%d", &x);Tmp = find(BST, x); //用一個容器,不然在一個元素未找到時會被置為NULL,先序遍歷無法輸出
       if (!Tmp) {printf("未找到該元素\n\n");} else {printf("找到%d\n\n", Tmp->data);} break;
      case 6: printf("先序遍歷如下:\n"); preOrder(BST);printf("\n\n");break;
      default: printf("請輸入合法操作!\n\n");break;
    }
    printf("1.插入元素   2.刪除元素   3.查詢最小值\n");
    printf("4.查詢最大值   5.查詢指定元素   6.先序輸出   7.退出\n");
  }
  return 0;
}



測試如下