反转链表 - 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<Box<ListNode>>
}


反转链表:

fn reverseList2(head :&mut Option<Box<ListNode>>) -> Option<Box<ListNode>> { 
	match *head{
		None => None,
		Some(head) => {
			let mut head = Some(head);
			let mut pNext = head.unwrap().next;
			let mut pPrevious:Option<Box<ListNode>> = 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<List>), 
    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); 
<span style="white-space:pre">	</span>println!("{:30}",result.stringify());
}

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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值