當前位置: 首頁>>數據結構>>正文


線段樹的實現[C語言](原創)

線段樹也是一種二叉樹,隻不過它的節點用來表示一個區間,其特征是將當前區間二分後分別作為左右孩子節點

的區間,如下圖(來自百度圖片)所示:

10

線段樹在處理區間覆蓋問題時,比較有用處,它支持的基本操作如下:

1)  給定區間[i, j],創建一個線段樹;【時間複雜度為O(j – i)】

2)  將某個區間[i,j]插入到線段樹中; 【時間複雜度為O(log(j-i))】

3)  從線段樹中刪除某個區間[i,j]。【時間複雜度為O(log(j-i)】

下麵是使用C語言實現的一個線段樹(VC++編譯器編譯運行):

/*
* Author:puresky
* Date: 2008/12/22
* Version: 線段樹1.0,
* Refer to:數據結構教程(V2)
*/
#include <stdio.h>
#include <stdlib.h>

typedef struct ltree_node
{
      int i, j; //表示區間[i, j]
      int cover; //表示區間被覆蓋的次數
      struct ltree_node *left, *right; //左右兒子節點
} LTree;

//創建線段樹

LTree* ltree_create(int i, int j)
{
      if(i > j) return (NULL);
      LTree* pNode = NULL;
      pNode = (LTree*)malloc(sizeof(LTree));
      pNode->i = i;
      pNode->j = j;
      pNode->cover = 0;
      if(j - i > 1)
      {
            int mid = i + (j - i) / 2;
            pNode->left = ltree_create(i, mid);
            pNode->right = ltree_create(mid, j);
      }
      else
      {
            pNode->left = pNode->right = NULL;
      }
      return pNode;
}

//插入一個區間

void ltree_insert(LTree* ltree, int i, int j)
{
      if(i > j) return;
      if(i <= ltree->i && ltree->j <= j)
      {
            ltree->cover++;
      }
      else
      {
            int mid = ltree->i + (ltree->j - ltree->i) / 2;
            if(j <= mid)
            {
                  ltree_insert(ltree->left, i, j);
            }
            else if(mid <= i)
            {
                  ltree_insert(ltree->right, i, j);
            }
            else
            {
                  ltree_insert(ltree->left, i, mid);
                  ltree_insert(ltree->right, mid, j);
            }
      }
}

//刪除一個區間,注意隻能刪除已經插入的區間
void ltree_delete(LTree* ltree, int i, int j)
{
      if(i > j) return;
      if(i <= ltree->i && ltree->j <= j)
            ltree->cover--;
      else
      {
            int mid = ltree->i + (ltree->j - ltree->i) / 2;
            if(j <= mid)
            {
                  ltree_delete(ltree->left, i, j);
            }
            else if(i >= mid)
            {
                  ltree_delete(ltree->right, i, j);
            }
            else
            {
                  ltree_delete(ltree->left, i, mid);
                  ltree_delete(ltree->right, mid, j);
            }
           
      }
}

//輸出線段樹

void ltree_print(LTree* ltree, int depth)
{
      if(ltree)
      {
            int i;
            for(i = 0; i < depth; ++i) printf("        ");
            printf("[%d,%d]:%d\n", ltree->i, ltree->j, ltree->cover);
           
            ltree_print(ltree->left, depth + 1);
            ltree_print(ltree->right, depth + 1);
      }
}

//釋放線段樹內存

void ltree_destroy(LTree* ltree)
{
      if(ltree)
      {
            LTree* pNode = ltree;
            ltree_destroy(ltree->left);
            ltree_destroy(ltree->right);
            //free(pNode);
      }
}

int main(int argc, char** argv)
{
     
      //測試線段樹
      LTree* root = ltree_create(1, 10);
      ltree_print(root, 0);
      ltree_insert(root, 3, 6);
      ltree_print(root, 0);
      ltree_insert(root, 7, 9);
      ltree_print(root, 0);
      ltree_delete(root, 3, 5);
      ltree_print(root, 0);
      ltree_destroy(root);
      system("pause");
      return 0;
}
本文由《純淨天空》出品。文章地址: https://vimsky.com/zh-tw/article/77.html,未經允許,請勿轉載。