单向链表的翻转

       单向链表翻转,之前把这个问题想的太简单了,以为只要把数据域翻转过来就可以了,结果是筐了大瓢,下面举一个简单的例子说明:

       假设有n个人站成一排,现在要把这n个人的站的顺序颠倒过来,那么就不能只把这n个人的身高颠倒过来,而是要把每一个人的位置颠倒过来,第一个人站到最后,第二个人站倒数第二,以此类推。

       为了检验程序的正确性,这一次我们打印时不能再打印结点数据,而要打印结点Java程序运行时,JVM为程序开辟了内存空间,每一个结点在栈中都有一个保存的位置,要注意的是,每次程序运行时某一个结点在内存中保存的位置并不是一定的,所以进行方法测试的时候一定要在一次运行中进行测试,这也是之前我一直纠结的问题,为什么打印的结点元素对了,但是结点却不同。

       下面来讲解一下我实现链表翻转的过程,在讲解正确方法之前先来看一下假翻转:

 

public void wrongturn(){
	for(int i=1;i<size();i++){
		insert(i,get(size()).obj);
		delete(size());
	}
}

这里的insert方法详见于我的上一篇博客当中

http://cq520.iteye.com/blog/1860061,这种做法的意思是,先把所有的结点都复制出来,再逆置插入链表中,每次插入之后就把最后一个多出来的结点删除掉,如果你只打印当前的链表元素很容易就被这种方法蒙蔽了,不过很明显,这种做法虽然能够达到逆置的效果,但是逆置的结点却全都变了,就像你换了一帮人来做这件事情一样,它们操作的内存地址不是同一块。

下面讲解正确的方法:

这是一个单链表:

 

 

1.       把尾结点放在首结点的前面,把首结点向后推移

 

 

2.       把当前的最后一个结点依次插入到链表的下一个位置

 

 

这句话大家可能有点不理解,其实在执行完第一步之后链表的长度并没变,只是最后一个结点已经变成了之前的倒数第二个结点,然后接下来要做的事情就是把当前的最后一个结点连接到新的头结点后面去(意思就是插入到第二个位置,这个头结点就是没变换前的last结点),执行完这一步之后,最后一个结点又会向前推移,变成倒数第三个结点,再把倒数第三个结点插入到第三个位置以此类推。

代码如下 :

/**
 * 翻转链表的方法
 */
public void turn(){
	//先把最后一个结点放在首结点的位置
	last.next=head;
	head=last;
        //依次从头到尾插入结点
	for(int i=1;i<size();i++){
		get(size()).next=get(i).next;
		get(i).next=get(size());
	}
	get(size()).next=null;
}

 

逆置的问题在实现上其实并不难,但是理解起来却并不容易,需要攻克的地方在于不要让同一块内存保存两个数据,也不要让链表中任何一个结点失去引用,而且原来结点在内存中表示也不要改变,这也是结点在引用时最容易看蒙的。

这只是实现翻转的一种方法,当然还有更多的方法等待挖掘,一些朋友们已经写出了其他的方法,希望大家也一起来寻找更多更好的方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值