• Introduction to Dynamic Set


      A Dynamic Set is an Abstract Data Type (ADT) that can support the following operations:

      (1)  search for an item to determine whether the item exists in the set;

      (2)  insert a new item into the set;

      (3)  delete a current item from the set.


    1. Binary Search Tree

      All the operations mentioned above have a time performance of O(h) in a Binary Search Tree (BST), where h is the height of the BST. In order to maintain the balance of such a binary tree and thus gain a relatively good time performance, sophisticated strategies are exploited in AVL Tree, Red-Black Tree and other advanced data structures. Here I would only provide a Java class of a naive binary search tree.

      1 class BST<T extends Comparable> {
      2     private class Node<T> {
      3         // Node of Binary Search Tree
      4         public Node<T> left, right;
      5         public T data;
      6     }
      7     
      8     private Node<T> root;     // root of Binary Search Tree
      9     private int minIdx;    // index aimed to help ithMin
     10     
     11     public boolean search(T item) {
     12         // Search for an item starting from the root
     13         //        return whether such an item exists
     14         return srchHelp(root,item)!=null;
     15     }
     16     private Node<T> srchHelp(Node<T> sub,T item) {
     17         // Search a Node that contains item as its data
     18         //        return such a Node of the minimum depth
     19         //        if no such Node exists, return null
     20         if (sub==null||sub.data.equals(item)) {
     21             return sub;
     22         } else if (sub.data.compareTo(item)<0) {
     23             return srchHelp(sub.right,item);
     24         } else {
     25             return srchHelp(sub.left,item);
     26         }
     27     }
     28     public void insert(T item) {
     29         // Insert an item to BST starting from root
     30         root = insHelp(root, item);
     31     }
     32     private Node<T> insHelp(Node<T> sub,T item) {
     33         // Insert an item to a subtree recursively
     34         if (sub==null) {
     35             sub = new Node<T>();
     36             sub.data = item;
     37         } else if (item.compareTo(sub.data)<0) {
     38             sub.left = insHelp(sub.left,item);
     39         } else {
     40             sub.right = insHelp(sub.right,item);
     41         }
     42         return sub;
     43     }
     44     public void delete(T item) {
     45         // Delete a Node with data item from BST
     46         root = delHelp(root,item);
     47     }
     48     public Node<T> delHelp(Node<T> sub,T item) {
     49         // Search an item and ultimately delete it
     50         if (sub==null) {
     51             return null;
     52         } else if (item.compareTo(sub.data)==0) {
     53             sub = delNode(sub);
     54         } else if (item.compareTo(sub.data)<0) {
     55             sub.left = delHelp(sub.left,item);
     56         } else {
     57             sub.right = delHelp(sub.right,item);
     58         }
     59         return sub;
     60     }
     61     private Node<T> delNode(Node<T> sub) {
     62         // Delete the Node sub given sub!=null
     63         if (sub.right==null) {
     64             return sub.left;
     65         } else if (sub.left==null) {
     66             return sub.right;
     67         } else if (sub.right.left==null) {
     68             sub.data = sub.right.data;
     69             sub.right = sub.right.right;
     70             return sub;
     71         } else {
     72             Node<T> prev = sub.right;
     73             while (prev.left.left!=null) {
     74                 prev = prev.left;
     75             }
     76             sub.data = prev.left.data;
     77             prev.left = prev.left.right;
     78             return sub;
     79         }
     80     }
     81     public void delLessThan(T item) {
     82         // Delete items less than item starting from root
     83         root = delLessThanHelp(root,item);
     84     }
     85     private Node<T> delLessThanHelp(Node<T> sub,T item) {
     86         // Delete items less than item from a subtree
     87         if (sub==null) {
     88             return null;
     89         } else if (sub.data.compareTo(item)<0) {
     90             sub.left = delLessThanHelp(sub.left,item);
     91             return delLessThanHelp(sub.right,item);
     92         } else {
     93             sub.left = delLessThanHelp(sub.left,item);
     94             return sub;
     95         }
     96     }
     97     public void delGreaterThan(T item) {
     98         // Delete items greater than item starting from root
     99         root = delGreaterThanHelp(root,item);
    100     }
    101     private Node<T> delGreaterThanHelp(Node<T>  sub,T item) {
    102         // Delete items greater than item from a subtree
    103         if (sub==null) {
    104             return null;
    105         } else if (sub.data.compareTo(item)>0) {
    106             sub.right = delGreaterThanHelp(sub.right,item);
    107             return delGreaterThanHelp(sub.left,item);
    108         } else {
    109             sub.right = delGreaterThanHelp(sub.right,item);
    110             return sub;
    111         }
    112     }
    113     public void delInterval(T a, T b) {
    114         // Delete items greater than a && less than b
    115         root = delIntervalHelp(root,a,b);
    116     }
    117     public Node<T> delIntervalHelp(Node<T> sub,T a,T b) {
    118         // Delete items belonging to (a,b) from a subtree
    119         if (a.compareTo(b)>=0) {
    120             return sub;
    121         } else if (sub==null) {
    122             return null;
    123         } else if (sub.data.compareTo(a)<=0) {
    124             sub.right = delIntervalHelp(sub.right,a,b);
    125         } else if (sub.data.compareTo(b)>=0) {
    126             sub.left = delIntervalHelp(sub.left,a,b);
    127         } else {
    128             sub.left = delIntervalHelp(sub.left,a,b);
    129             sub.right = delIntervalHelp(sub.right,a,b);
    130             sub = delNode(sub);
    131         }
    132         return sub;
    133     }
    134     public T ithMin(int idx) {
    135         // Return the idx-th least item in BST
    136         if (idx<=0) {
    137             return null;
    138         } else {
    139             minIdx = idx;
    140             return ithMinHelp(root);
    141         }
    142     }
    143     private T ithMinHelp(Node<T> sub) {
    144         // Return the minIdx-th least item recursively
    145         if (sub==null) {
    146             return null;
    147         } else {
    148             T val = ithMinHelp(sub.left);
    149             if (minIdx<=0) {
    150                 // counting has been terminated
    151                 return val;
    152             } else if (--minIdx==0) {
    153                 // termination of counting
    154                 return sub.data;
    155             } else {
    156                 // counting is going on
    157                 return ithMinHelp(sub.right);
    158             }
    159         }
    160     }
    161     public void display()  {
    162         inOrderTraverse(root);
    163         System.out.println();
    164     }
    165     private void inOrderTraverse(Node<T> sub) {
    166         if (sub!=null) {
    167             inOrderTraverse(sub.left);
    168             System.out.print("	"+sub.data);
    169             inOrderTraverse(sub.right);
    170         }
    171     }
    172 }

    2. Hash Table

      In a Hash Table, a hash function maps an item to its proper slot in the table and thus each set operation can gain a time performance of O(1). To tackle the problem of what is called "conflict", we can resort to either Open Hashing or Chaining. Here, I used a chaining hash table to solve a problem from SJTU ACM Online Judge,

     1 import java.util.*;
     2 
     3 class Hash  {
     4     private class Node {
     5         public int data;
     6         public int cnt = 1;
     7         public Node next;
     8     }
     9     
    10     private final int SIZE = 100003;
    11     private Node[] tbl;
    12     
    13     public Hash() {
    14         tbl = new Node[SIZE];
    15         for (int i=0;i<SIZE;i++) {
    16             tbl[i] = new Node();
    17         }
    18     }
    19     private int index(int item) {
    20         // Hash function using division method
    21         if (item%SIZE<0) {
    22             return item%SIZE+SIZE;
    23         } else {
    24             return item%SIZE;
    25         }
    26     }
    27     public void insert(int item) {
    28         // Insert an item to the hash table
    29         Node itr = tbl[index(item)];
    30         while (itr.next!=null) {
    31             if (itr.next.data==item) {
    32                 itr.next.cnt++;
    33                 return;
    34             } else {
    35                 itr = itr.next;
    36             }
    37         }
    38         itr.next = new Node();
    39         itr.next.data = item;
    40     }
    41     public int search(int item) {
    42         // Search an item in the hash table
    43         //        return its count value
    44         Node itr = tbl[index(item)].next;
    45         while (itr!=null) {
    46             if (itr.data==item) {
    47                 return itr.cnt;
    48             } else {
    49                 itr = itr.next;
    50             }
    51         }
    52         return 0;
    53     }
    54 }
    55 
    56 public class Main {
    57     public static void main(String[] args) {
    58         // get and store the input data
    59         Scanner in = new Scanner(System.in);
    60         int num = in.nextInt();
    61         int[][] table = new int [num][4];
    62         for (int i=0;i<num;i++) {
    63             table[i][0] = in.nextInt();
    64             table[i][1] = in.nextInt();
    65             table[i][2] = in.nextInt();
    66             table[i][3] = in.nextInt();
    67         }
    68         in.close();
    69         // build up the hash table
    70         Hash set = new Hash();
    71         for (int i=0;i<num;i++) {
    72             for (int j=0;j<num;j++) {
    73                 set.insert(table[i][0]+table[j][1]);
    74             }
    75         }
    76         // solve the problem and print the result
    77         int val = 0;
    78         for (int i=0;i<num;i++) {
    79             for (int j=0;j<num;j++) {
    80                 val += set.search(-table[i][2]-table[j][3]);
    81             }
    82         }
    83         System.out.println(val);
    84     }
    85 
    86 }

    P.S.  关于链表的操作比较易错的是遍历的同时删除结点,应该这样做:

     1     private void srchAndDel(int del) {
     2         Node itr = tbl[index(item)];
     3         while (itr.next!=null) {
     4             if (itr.next.data==item) {
     5                 itr.next = itr.next.next;
     6                 continue;    //    Attention!
     7             }
     8             itr = itr.next;
     9         }
    10     }

    3. Cantor Expansion

      In the example above, I constructed a hash function by Division Method and this may seem more than facile. However, in other cases, the construction of a proper hash function may be a rather tricky work, which involves a lot of mathematical knowledge. Here, I'd like to take Cantor Expansion for example, a bijection that maps a permutation of n distinct integers to a natural number index in a hash table.

     1     public static int cantor(int[] perm) {
     2         // Encode a 0 through n-1 permutation into an index
     3         int val = 0, len = perm.length;
     4         int[] cnt = new int[len];
     5         boolean[] vis = new boolean[len];
     6         for (int i=0;i<len;i++) {
     7             for (int j=0;j<perm[i];j++) {
     8                 // cnt[i] is the number of unvisited numbers
     9                 //        that are smaller than perm[i]
    10                 cnt[i] += (vis[j])? 0:1;
    11             }
    12             vis[perm[i]] = true;
    13         }
    14         for (int i=0;i<len;i++) {
    15             val = val*(len-i)+cnt[i];
    16         }
    17         return val;
    18     }
    19     public static void cantInv(int code,int[] perm) {
    20         // Decode an index into a 0 through n-1 permutation
    21         int len = perm.length;
    22         int[] fact = new int[len];
    23         fact[0] = 1;
    24         for (int i=1;i<len;i++) {
    25             // fact[i] stores i factorial
    26             fact[i] = fact[i-1]*i;
    27         }
    28         boolean[] vis = new boolean[len];
    29         for (int i=0;i<len;i++) {
    30             int cnt = code/fact[len-i-1];
    31             for (int j=0;j<len;j++) {
    32                 // perm[i] is the (cnt+1) th smallest one among unvisited items
    33                 if (!vis[j]&&--cnt<0) {
    34                     perm[i] = j;
    35                     break;
    36                 }
    37             }
    38             vis[perm[i]] = true;
    39             code %= fact[len-i-1];
    40         }
    41     }
  • 相关阅读:
    fscanf_s与scanf_s的宽度参数与缓冲区参数分析
    C语言小程序——推箱子(窄字符和宽字符)
    setlocale()函数详解——C语言
    在源文件(.c)和头文件(.h)中声明和定义的区别——C语言
    枚举类型enum详解——C语言
    宽字符————_T、_TEXT、L、TEXT之间的区别
    宽字符wchar_t和窄字符char——putwchar、wprintf
    extern的使用详解(多文件编程)——C语言
    编程的时候命名词穷了怎么办
    [C#/UI] 使用 await 实现业务对 UI 的控制反转
  • 原文地址:https://www.cnblogs.com/DevinZ/p/4411448.html
Copyright © 2020-2023  润新知