سؤال

وهكذا إيف حصلت على هذا الحق جمع كبير الحمار؟ في شجرة المدعومة (RBTree)، وذلك للبحث المنبثقة سريعة، ويتم فرز القيم.

حصل

ويقول إيف قيمة X. يمكنني بالبحث X في بلدي شجرة في الوقت logn، بارد. ولكن أريد القيم على يمين X في شجرة كذلك، حتى واحد منهم dosent تلبية الاختبار. أي الحصول على جميع العناصر التي هي> = X و

أنا <م> يمكن الحصول على مؤشر X، ط، ثم الحصول على قيمة في الاول + 1، ط + 2 .... حتى فال (ط + ض) هو> Y. إلا أن تكاليف ض * logn. إذا كنت تعداد فوق الشجرة، العداد داخل الشجرة التكلفة] لا logn للمضي قدما إلى العنصر التالي - انها مجرد يتبع المؤشر في الشجرة.

وهكذا، ليس هناك وسيلة لبدء تعداد من مؤشر معين؟ بحيث أنا لا أميل لها لتخطي ط العناصر قبل أن أتمكن من بدء تعداد على نطاق أريد.

وأخبرني إذا كنت تعتقد ايم مجنون.

هل كانت مفيدة؟

المحلول

حسنا، إذا كنت وضعت العناصر في مجموعتك هناك نفسك، وكنت لا تمانع فرزها قبل الإدراج، هل يمكن أن التفاف عليها مع نوع قائمة مرتبطة. فقط تأكد من أن مفتاح لربط المجمع عنصر القائمة لكل عنصر يستخدم مفتاح العنصر كما مفتاحه لنوع الشجرة. ثم بحث سوف تحصل على موقع في قائمة مرتبطة، وهل يمكن أن مجرد المشي من هناك.

ولكن، إذا كنت لا تستطيع أن تفعل ذلك بهذه الطريقة، فليس أمامك سوى لتعديل RBTree، الأمر الذي يتطلب القليل من العمل في C، لأنه هو امتداد الأصلي إلى روبي. معظم القطع التي تحتاجها هناك dict_lookup() لتعطيك عقدة في شجرة تحتاج بالفعل، وrbtree_for_each() لتظهر لك كيفية كتابة مكرر، نظرا عقدة البداية.

وأنت قد لإضافة التعليمات البرمجية التالية إلى rbtree.c في جوهره RBTree:

*** rbtree.c.orig 2009-03-27 14:14:55.000000000 -0400
--- rbtree.c  2009-03-27 14:20:21.000000000 -0400
***************
*** 528,533 ****
--- 528,574 ----
      return EACH_NEXT;
  }

+ static VALUE
+ rbtree_each_starting_with_body(rbtree_each_arg_t* arg)
+ {
+     VALUE self = arg->self;
+     dict_t* dict = DICT(self);
+     dnode_t* node;
+     
+     ITER_LEV(self)++;
+     for (node = (dnode_t*) arg->arg;
+          node != NULL;
+          node = dict_next(dict, node)) {
+         
+         if (arg->func(node, NULL) == EACH_STOP)
+             break;
+     }
+     return self;
+ }
+ 
+ /*
+  * call-seq:
+  *   rbtree.each_starting_with(key) {|key, value| block} => rbtree
+  *
+  * Calls block once for each key in order, starting with the given key,
+  * passing the key and value as a two-element array parameters.
+  */
+ VALUE
+ rbtree_each_starting_with(VALUE self, VALUE key)
+ {
+     dnode_t* node = dict_lookup(DICT(self), TO_KEY(key));
+     rbtree_each_arg_t each_arg;
+     if (node == NULL) { return self; };
+     
+     RETURN_ENUMERATOR(self, 0, NULL);
+ 
+     each_arg.self = self;
+     each_arg.func = each_i;
+     each_arg.arg = node;
+     return rb_ensure(rbtree_each_starting_with_body, (VALUE)&each_arg,
+                      rbtree_each_ensure, self);
+ }
+ 
  /*
   * call-seq:
   *   rbtree.each {|key, value| block} => rbtree
***************
*** 1616,1621 ****
--- 1657,1663 ----
      rb_define_method(MultiRBTree, "length", rbtree_size, 0);

      rb_define_method(MultiRBTree, "each", rbtree_each, 0);
+     rb_define_method(MultiRBTree, "each_starting_with", rbtree_each_starting_with, 1);
      rb_define_method(MultiRBTree, "each_value", rbtree_each_value, 0);
      rb_define_method(MultiRBTree, "each_key", rbtree_each_key, 0);
      rb_define_method(MultiRBTree, "each_pair", rbtree_each_pair, 0);

وبعد ذلك إذا قمت بتشغيل make في الدليل المصدر من الأحجار الكريمة rbtree تثبيت، فإنه يجب إعادة تشكيل التمديد، ويمكنك استخدامه بشكل طبيعي:

% irb
irb> require 'rubygems'
=> true
irb> require 'rbtree'
=> true
irb> x = RBTree[ 'a', 1, 'b', 2, 'c', 3, 'd', 4 ]
=> #<RBTree: {"a"=>1, "b"=>2, "c"=>3, "d"=>4}, default=nil, cmp_proc=nil>
irb> x.each { |k,v| p [k, v] }
["a", 1]
["b", 2]
["c", 3]
["d", 4]
=> #<RBTree: {"a"=>1, "b"=>2, "c"=>3, "d"=>4}, default=nil, cmp_proc=nil>
irb> x.each_starting_with('b') { |k,v| p [k, v] }
["b", 2]
["c", 3]
["d", 4]
=> #<RBTree: {"a"=>1, "b"=>2, "c"=>3, "d"=>4}, default=nil, cmp_proc=nil>

ونتذكر فقط التي قمت بها هذا التغيير، وتوزيع جوهرة المعدلة مع التغييرات. أو، مهلا، رفعها إلى الخالق جوهرة على Rubyforge ، بحيث يمكن للجميع الاستفادة منها.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top