在具有节点中多个元素的B树中递归地找到第k个最小元素

时间:2018-06-03 09:19:26

标签: c algorithm data-structures b-tree

假设我们有以下b-tree

b-tree

我想创建一个算法,以便找到第k个最小的元素。我试图实现这个link中写的内容,但我发现没有一个解决方案似乎适用于这种树。

到目前为止,我已经完成了这项工作,对于最后一个分支

的元素运行良好
i <-0
function kthSmallestElement(Node node, int k)
    if(branch[i] != NULL) then
        size<-branch[i].size();
    if(k < size) then
        i++;
        call the function recursively for new branch[i], k
    else if(k > size) then
        k-=size
        i++;
        call the function recursively for new branch[i], k
    else if (k==size) then
        print branch[i]->entry[k-1]
    else
        print brach[i-1]->entry[k-1]
end function

我使用C

实现了算法
#define MAX 4      /* maximum number of keys in node. */
#define MIN 2      /* minimum number of keys in node */

typedef int Key;

typedef struct {
   Key key;
   int value;     /* values can be arbitrary */
} Treeentry;


typedef enum {FALSE, TRUE} Boolean;

typedef struct treenode Treenode;

struct treenode {
  int count;     /* denotes how many keys there are in the node */
    /*
        The entries at each node are kept in an array entry 
          and the pointers in an array branch
    */
  Treeentry entry[MAX+1];
  Treenode *branch[MAX+1];
};

int i = 0;
int size = 0;
void FindKthSmallestElement(Treenode *rootNode, int k){
  if(branch[i] != NULL) //since the node has a child
    size = branch[i] ->count;
    if(k < size){
      i++;
      FindKthSmallestElement(branch[i], k);
    }else if(k > size){
      k-=size;
      i++;
      FindKthSmallestElement(branch[i], k);
    }else if (k==size)
      printf ("%d", branch[i]->entry[k-1].key);
    else
      printf ("%d", brach[i-1]->entry[k-1].key);
}

为了获得每个第k个最小元素的有效输出,你能否建议我应该解决这个问题?我倾向于认为这个问题不能递归地解决,因为我们在每个节点中有多个条目。将它变成像link这样的堆树是明智的吗?

2 个答案:

答案 0 :(得分:2)

这个问题可以递归解决。您所需要的只是让函数返回两件事:

  1. 第k个最小的键(或指向它的指针),如果它有k个或更多个键。
  2. 树的大小如果小于k键。
  3. 通过在(根)节点的每个子树上连续地从最左边到最右边调用函数并使用不同的(递减的)参数k来进行递归:

    • 让原始/当前树为R,通过调用R最左边的子树上的函数开始递归,其中k与R接收的k相同。
    • 如果在R的子树上调用函数成功返回第k个最小的键,那么答案就会返回。
    • 如果在R的某个子树T上调用该函数找不到第k个最小的键,而是返回T的大小,比如n(&lt; k),则:
      • 如果T是最右边的子树,那么R少于k项,返回R的大小(通过将所有子树的大小和R中的键数相加来找到它们。根)。
      • 如果n == k-1,则第k个最小的键是紧靠T右侧的键
      • 如果n < k-1,然后在参数k-n-1的T右边的子树S上递归(即,找到S中的第(k-n-1)个最小的密钥)

    显然,您必须处理树的根不再具有子树的终端条件。从概念上讲,通过允许包含0键的NULL子树可以更容易地处理它。

答案 1 :(得分:1)

递归访问每个节点,并将当前节点的k个最小元素添加到列表中。最后排序并获得第k个数字。

你也可以尝试比较2个列表并每次保持k个最小的列表,但我认为它会使代码看起来更复杂并且最终会以大致相同或更差的速度结束,但肯定会减少内存占据。