मैं एक बाइनरी सर्च ट्री कार्यान्वयन में एक सम्मिलित फ़ंक्शन पर काम कर रहा हूं। यहाँ मेरा कोड है:

pub struct Node {
    data: i32,
    left: Option<Box<Node>>,
    right: Option<Box<Node>>
}

fn insert_at_root(mut root_node: Node, new_node: Node) -> Node { //not reference because root_node will be mutated
    if root_node.data > new_node.data { // value less than root
        if let Some(left) = root_node.left {
            insert_node(*left, new_node); // *left is a way to downcast box, i.e. *left = T from Box<T>
        }
        else {
            root_node.set_left(Some(Box::new(new_node)));
        }
    }
    else if root_node.data < new_node.data {
        if let Some(right) = root_node.right {
            insert_node(*right, new_node);
        }
        else {
            root_node.set_right(Some(Box::new(new_node)));
        }
    }
    root_node
}

fn insert_node(mut exist_node: Node, new_node: Node) -> () {
    if exist_node.data > new_node.data {
        if let Some(left) = exist_node.left {
            insert_node(*left, new_node);
        }
        else {
            exist_node.set_left(Some(Box::new(new_node)));
        }
    }
    else if exist_node.data < new_node.data {
        if let Some(right) = exist_node.right {
            insert_node(*right, new_node);
        }
        else {
            exist_node.set_right(Some(Box::new(new_node)));
        }
    }
}

मेरे पास दो सम्मिलित कार्य हैं, इसलिए जब मैं insert_at_node को कॉल करता हूं तो मैं चर को रूट नोड के साथ संरक्षित कर सकता हूं।

मेरी वर्तमान समस्या insert_at_root फ़ंक्शन में लाइन if let Some(left) = root_node.left { (और लाइन if let Some(right) = root_node.right {) है जो स्पष्ट रूप से एक चाल का कारण बनती है। परिणामस्वरूप, मैं insert_at_node के अंत में root_node वापस नहीं आ सकता:

error[E0382]: use of moved value: `root_node`
  --> src/lib.rs:34:5
   |
19 |         if let Some(left) = root_node.left {
   |                     ---- value moved here
...
34 |     root_node
   |     ^^^^^^^^^ value used here after partial move
   |
   = note: move occurs because value has type `std::boxed::Box<Node>`, which does not implement the `Copy` trait

error: aborting due to previous error

उन पंक्तियों का उद्देश्य यह जांचना है कि क्या left (या right) चाइल्ड नोड None नहीं है, मूल रूप से root_node.left != None। क्या कोई कदम उठाए बिना इसे हासिल करने का कोई तरीका है? हो सकता है कि != या == चिन्ह वाला कुछ हो।

0
Oneiros 18 अप्रैल 2020, 18:07

1 उत्तर

सबसे बढ़िया उत्तर

आपको समस्या यह नहीं है कि आप परीक्षण करते हैं कि left/right Some है या None। BTW जो .is_some() और .is_none() परीक्षणों के साथ किया जा सकता है।

आपकी समस्या यह है कि आप वेरिएबल left को Node से बांधते हैं जो कि Option में है। इसके द्वारा आप Option की सामग्री के स्वामित्व को left चर में स्थानांतरित कर देते हैं।

सामान्य तौर पर यदि आप स्वामित्व को स्थानांतरित नहीं करना चाहते हैं, तो आपको संदर्भों के साथ काम करना होगा। जब कभी वैरिएबल एक Option के अंदर होता है और आपको इसके अंदर एक संदर्भ के रूप में देखने की आवश्यकता होती है, तो आपको इसके प्रकार को Option<T> से Option<&T> में बदलना होगा। जब तक आप विकल्प के अंदर देखते हैं, तब तक यह केवल एक संदर्भ होता है, और इसलिए स्वामित्व को स्थानांतरित नहीं करता है।

Option पर दो फ़ंक्शन उपलब्ध हैं जो इस रूपांतरण को करते हैं: .as_ref() एक अपरिवर्तनीय संदर्भ में कनवर्ट करने के लिए, और .as_mut() जो एक परिवर्तनीय संदर्भ में कनवर्ट करता है। चूंकि आप left की सामग्री को संशोधित करना चाहते हैं, इसलिए आपको एक परिवर्तनीय संदर्भ की आवश्यकता है, इसलिए .as_mut() जैसा आप चाहते हैं।

.as_mut() left का उपयोग करने से आपको वैरिएबल के बजाय एक संदर्भ मिलता है, इसलिए कोई स्वामित्व स्थानांतरित नहीं किया गया था।

आपको मिलने वाली अगली समस्या यह है कि आप किसी संदर्भ को insert_node में पास नहीं कर सकते क्योंकि इस फ़ंक्शन के प्रकार के हस्ताक्षर को संदर्भ के बजाय चर प्राप्त करने की आवश्यकता होती है। इसके द्वारा यह आवश्यक होगा कि आप इस सहायक कार्य के अंदर स्वामित्व पास करें, इसलिए यह भी काम नहीं करेगा। इसलिए हम insert_node के हस्ताक्षर को Node के बजाय &mut Box<Node> में बदल देते हैं। तो फिर हम केवल एक संदर्भ लेते हैं, स्वामित्व नहीं।

pub fn insert_at_root(mut root_node: Node, new_node: Node) -> Node {
    //not reference because root_node will be mutated
    if root_node.data > new_node.data {
        // value less than root
        if let Some(left) = root_node.left.as_mut() {
            insert_node(&mut *left, new_node);
        } else {
            root_node.set_left(Some(Box::new(new_node)));
        }
    } else if root_node.data < new_node.data {
        if let Some(right) = root_node.right.as_mut() {
            insert_node(&mut *right, new_node);
        } else {
            root_node.set_right(Some(Box::new(new_node)));
        }
    }
    root_node
}

pub fn insert_node(exist_node: &mut Box<Node>, new_node: Node) -> () {
    if exist_node.data > new_node.data {
        if let Some(left) = exist_node.left.as_mut() {
            insert_node(&mut *left, new_node);
        } else {
            exist_node.set_left(Some(Box::new(new_node)));
        }
    } else if exist_node.data < new_node.data {
        if let Some(right) = exist_node.right.as_mut() {
            insert_node(&mut *right, new_node);
        } else {
            exist_node.set_right(Some(Box::new(new_node)));
        }
    }
}
3
Matthias Wimmer 18 अप्रैल 2020, 17:34