はじめに
本記事は 三重大学 計算研 Advent Calendar 2019 18日目です。
大学一年生の@scoopです。
Rustの文法の練習とデータ構造の勉強を兼ねてRustで二分探索木を書いてみました。
プログラミング初心者ですので、何か誤りや改善点等ございましたらご指摘いただけると幸いです。
実装について
概要
機能は作成、空判定、挿入、削除のみです。unsafe
な機能やRc<RefCell<T>>
は使用していません。
定義
Ord
、Default
を実装する型を要素に持てます。
#[derive(Debug)]structBST<T:Ord>{root:Option<Box<Node<T>>>,}#[derive(Debug)]structNode<T:Ord>{val:T,left:Option<Box<Node<T>>>,right:Option<Box<Node<T>>>,}
作成
pubfnnew()->Self{BST{root:None}}
空判定
pubfnis_empty(&self)->bool{self.root.is_none()}
挿入
pubfninsert(&mutself,val:T){letmutroot=self.root.take();self.insert_rec(&mutroot,val);self.root=root;}fninsert_rec(&self,node:&mutOption<Box<Node<T>>>,val:T){matchnode{Some(node)=>{ifnode.val>val{self.insert_rec(&mutnode.left,val);}elseifnode.val<val{self.insert_rec(&mutnode.right,val);}}None=>{*node=Some(Box::new(Node{val:val,left:None,right:None,}))}}}
削除
あまり上手く実装できておらず、remove_node()
、remove_rec_min()
などは非常に汚くなってしまっています。
pubfnremove(&mutself,val:T){letmutroot=self.root.take();self.remove_rec(&mutroot,val);self.root=root;}fnremove_rec(&self,node:&mutOption<Box<Node<T>>>,val:T){ifletSome(mutn)=node.take(){*node=match&val.cmp(&n.val){Equal=>{letmuttemp=Some(n);self.remove_node(&muttemp);temp}Less=>{self.remove_rec(&mutn.left,val);Some(n)}Greater=>{self.remove_rec(&mutn.right,val);Some(n)}}}}fnremove_node(&self,node:&mutOption<Box<Node<T>>>){ifletSome(mutn)=node.take(){*node=match(n.left.take(),n.right.take()){(None,None)=>None,(x@Some(_),None)|(None,x@Some(_))=>x,(l@Some(_),mutr@Some(_))=>{n.left=l;std::mem::replace(&mutn.val,self.remove_rec_min(&mutr));n.right=r;Some(n)}}}}fnremove_rec_min(&self,node:&mutOption<Box<Node<T>>>)->T{ifletSome(mutn)=node.take(){letans;*node=ifn.left.is_some(){ans=self.remove_rec_min(&mutn.left);Some(n)}else{ans=std::mem::take(&mutn.val);letmuttn=Some(n);self.remove_node(&muttn);tn};returnans;}unreachable!()}
全体
#[derive(Debug)]structBST<T:Ord>{root:Option<Box<Node<T>>>,}#[derive(Debug)]structNode<T:Ord>{val:T,left:Option<Box<Node<T>>>,right:Option<Box<Node<T>>>,}impl<T:Ord+Default>BST<T>{pubfnnew()->Self{BST{root:None}}pubfnis_empty(&self)->bool{self.root.is_none()}pubfninsert(&mutself,val:T){letmutroot=self.root.take();self.insert_rec(&mutroot,val);self.root=root;}fninsert_rec(&self,node:&mutOption<Box<Node<T>>>,val:T){matchnode{Some(node)=>{ifnode.val>val{self.insert_rec(&mutnode.left,val);}elseifnode.val<val{self.insert_rec(&mutnode.right,val);}}None=>{*node=Some(Box::new(Node{val:val,left:None,right:None,}))}}}pubfnremove(&mutself,val:T){letmutroot=self.root.take();self.remove_rec(&mutroot,val);self.root=root;}fnremove_rec(&self,node:&mutOption<Box<Node<T>>>,val:T){ifletSome(mutn)=node.take(){*node=match&val.cmp(&n.val){Equal=>{letmuttemp=Some(n);self.remove_node(&muttemp);temp}Less=>{self.remove_rec(&mutn.left,val);Some(n)}Greater=>{self.remove_rec(&mutn.right,val);Some(n)}}}}fnremove_node(&self,node:&mutOption<Box<Node<T>>>){ifletSome(mutn)=node.take(){*node=match(n.left.take(),n.right.take()){(None,None)=>None,(x@Some(_),None)|(None,x@Some(_))=>x,(l@Some(_),mutr@Some(_))=>{n.left=l;std::mem::replace(&mutn.val,self.remove_rec_min(&mutr));n.right=r;Some(n)}}}}fnremove_rec_min(&self,node:&mutOption<Box<Node<T>>>)->T{ifletSome(mutn)=node.take(){letans;*node=ifn.left.is_some(){ans=self.remove_rec_min(&mutn.left);Some(n)}else{ans=std::mem::take(&mutn.val);letmuttn=Some(n);self.remove_node(&muttn);tn};returnans;}unreachable!()}}
今後の課題
remove_node()
、remove_rec_min()
をきれいに書き直す。Default
を実装していない型にも使えるようにする。- 所属判定などの実装。