反转链表 - java和rust的不同实现


由于ownership的机制和不存在空指针的情况,很多在其他带GC的语言能够跑起来的程序在rust下面就要换一种做法。最近试用rust的基础数据结构时,更加加强了我的看法。下面以最原始的链表list为例。


在Java中,考虑最基本的链表定义

class ListNode {
		int val;
		ListNode next;

		ListNode(int x) {
			val = x;
		}

		@Override
		public String toString() {
			StringBuilder sb = new StringBuilder();
			sb.append("[");
			sb.append(val);
			ListNode pNext = this.next;
			while (pNext != null) {
				sb.append(",");
				sb.append(pNext.val);
				pNext = pNext.next;
			}
			sb.append("]");
			return String.format("%s", sb.toString());
		}
	}


如果我们要反转链表,可以这么做 

public ListNode reverseList(ListNode head) {
		if (head == null) {
			return null;
		}
		ListNode pNext = head.next;
		ListNode pPrevious = null;
		while (head != null) {
			pNext = head.next;
			head.next = pPrevious;
			pPrevious = head;
			head = pNext;
		}
		return pPrevious;
	}

那如果我们按照一般思维,在rust里对应的实现就是这样子的:

struct ListNode{
	id :i32,
	next :Option>
}


反转链表:

fn reverseList2(head :&mut Option>) -> Option> { 
	match *head{
		None => None,
		Some(head) => {
			let mut head = Some(head);
			let mut pNext = head.unwrap().next;
			let mut pPrevious:Option> = None;
			while true {
				match head {
					None =>{break;}
					_ =>{}
				}
				pNext = head.unwrap().next;
				head.unwrap().next = pPrevious;
				pPrevious = head;
				head = pNext;
			}
			pPrevious
		}
	}	 
}
然后编译,报了以下错误:


=》 match *head{

ERROR:cannot move out of borrowed content

=》  pNext = head.unwrap().next; 

ERROR:cuse of moved value: `head` 

这些错误就是因为rust的ownership机制,让我们无法像java或者c++里保存临时变量,特别是在循环里。反复试过各种写法,都行不通。


最后,换成这么来做

链表定义:

use List::*;

enum List { 
    Cons1(i32, Box), 
    Nil,
}

// Methods can be attached to an enum
impl List { 
     #[inline]
    fn new() -> List { 
        Nil
    }
 
    #[inline]
    fn prepend(self, elem: i32) -> List { 
        Cons1(elem, Box::new(self))
    }

    fn len(&self) -> i32 { 
        match *self { 
            Cons1(_, ref tail) => 1 + tail.len(), 
            Nil => 0
        }
    }

    fn stringify(&self) -> String {
        match *self {
            Cons1(head, ref tail) => { 
                format!("{}, {}", head, tail.stringify())
            },
            Nil => {
                format!("Nil")
            },
        }
    }
}

fn reverseList(list:List, acc:List ) -> List{
	match list{
		Cons1(val,tail) => {
			reverseList(*tail,acc.prepend(val))
		}
		Nil => acc
	}
} 


fn main() {   
	let mut head = List::new(); 
	let mut i=0; 
	while i < 10 {
		i+=1;
		head = head.prepend(i);
	}
	println!("{:30}",head.stringify());
	let result = List::new();
	let result = reverseList(head,result); 
	println!("{:30}",result.stringify());
}

从结果可以看到,链表已经实现反转了。所以在rust下面,很多做法都要换一下。有人说这就是rust函数式编程的思维。我但愿这种递归式的做法不会有溢出。


你可能感兴趣的:(rust)