链表的反转(递归和迭代)--算法笔记

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_44494648/article/details/102223339

链表的反转


1、迭代(C)

迭代好理解,是从链表头开始反转,直到链表的尾,这个方法要注意不能丢失后面的结点。

//结点
typedef struct Node{
	int num;
	struct Node *next;
}node;
//注意这里没有返回值,是因为这个链表带有头节点,反转的是头节点后面的部分
void exchange(node *pHead){
	node *p=pHead;
	node *m,*i,*j,*k;
	k=m=p->next;
	i=m->next;
	while(i){
		j=i->next;
		i->next=m;
		m=i;
		i=j;
	}
	k->next=NULL;
	p->next=m;
}

没有头节点的链表,可以加上以头结点,处理完成之后再去掉,这样可以简化操作步骤。

//结点
typedef struct Node{
	int num;
	struct Node *next;
}node;
//由于没有头节点,所以要有返回值
node*  exchange(node *pHead){
	//添加头节点
	node* a=(node*)malloc(sizeof(noide));
	a->next=pHead;
	a=pHead;
	
	//开始反转,与上面的步骤相同
	node *p=pHead;
	node *m,*i,*j,*k;
	k=m=p->next;
	i=m->next;
	while(i){
		j=i->next;
		i->next=m;
		m=i;
		i=j;
	}
	k->next=NULL;
	//p->next=m;直接将m返回,就是新的头指针,
	free(a);
	return m;
	
}

2、递归(Java)

反转不好操作的原因是会丢失上一个节点的地址,其实可以将每一个结点,压入一栈,之后再出栈,这样就不会出现找不到前驱结点的问题,可以从链表尾层层回退到链表头;

class Solution206 {
    public ListNode NHead;//保存尾结点,就是之后的新头节点
    //传入链表头
    public ListNode reverseList(ListNode head) {
    	//链表为空直接返回
        if(head==null){
            return head;
        }
        //链表不空,开始递归
        reverse(head);//开始递归
        head.next=null;//头变成了尾巴,所以最后的结点的next置空
        return NHead;
    }
    void reverse(ListNode tmp){
    	//将每个结点,从头到尾要入栈中,利用递归的调用处理方法
        if(tmp.next!=null){
            reverse(tmp.next);
            tmp.next.next=tmp;//让前一个指向自己
        }else
        {
            NHead=tmp;//找到尾结点并保存
            return;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_44494648/article/details/102223339