指针强化训练—1— 链表就地逆置 Java & C

93 篇文章 0 订阅
7 篇文章 0 订阅

以单链表作为存储结构,实现线性表的就地逆置。

Java实现

package com.programmercarl.linkedlist.homework;

import lombok.AllArgsConstructor;
import lombok.Builder;

/**
 * @ClassName ListNode
 * @Descriotion 单链表的结点
 * @Author nitaotao
 * @Date 2022/5/2 17:24
 * @Version 1.0
 **/
@AllArgsConstructor
@Builder
public class ListNode {
    /**
     * 结点的值
     */
    public Integer val;

    /**
     * 下一个结点
     */
    public ListNode next;

    /**
     * 无参构造
     */
    public ListNode() {
    }

    /**
     * 带参构造 1
     */
    public ListNode(int val) {
        this.val = val;
    }

    /**
     * 带参构造 2
     */
    public ListNode(int val, ListNode next) {
        this.val = val;
        this.next = next;
    }

    @Override
    public String toString() {
        ListNode cur = this;
        while (cur.next != null&&cur.next!=this) {
            System.out.print(cur.val+" ");
            cur=cur.next;
        }
        System.out.println(cur.val);
        return null;
    }
}


package com.programmercarl.linkedlist.homework;

/**
 * @ClassName ListReverse
 * @Descriotion TODO
 * @Author nitaotao
 * @Date 2022/5/5 13:31
 * @Version 1.0
 **/
public class ListReverse {
    public static void main(String[] args) {
        ListNode node5 = ListNode.builder().val(5).next(null).build();
        ListNode node4 = ListNode.builder().val(4).next(node5).build();
        ListNode node3 = ListNode.builder().val(3).next(node4).build();
        ListNode node2 = ListNode.builder().val(2).next(node3).build();
        ListNode node1 = ListNode.builder().val(1).next(node2).build();
        listReverse(node1);
    }

    public static void listReverse(ListNode node) {
        //当前结点
        ListNode temp1 = new ListNode();
        //当前结点下一个结点
        ListNode temp2 = new ListNode();
        //处理头结点
        if (node == null) {
            return;
        }
        //只有1个结点
        if (node.next == null) {
            System.out.println(node.val);
            return;
        } else {
            temp1.next = node;
            if (node.next.next != null) {
                temp2.next = node.next;
                node.next = null;
            } else {
                //只有2个结点
                node.next.next = node;
                node.next = null;
                return;
            }
        }
        //当有下个结点
        ListNode temp;
        while (temp2.next.next != null) {
            //下下个结点
            temp = ListNode.builder().next(temp2.next.next).build();
            //原链表结点断开,变换
            temp2.next.next = temp1.next;
            //当前结点后移
            temp1.next = temp2.next;
            //当前结点下一个结点后移
            temp2.next = temp.next;
        }
        //最后一个结点
        temp2.next.next = temp1.next;
        node.next = temp2.next;
    }
}

C实现

//
// Created by nitaotao on 2022/5/7->
//

#include <malloc.h>
#include <stdio.h>

//单链表的就地逆置
//定义结点
typedef struct ListNode {
    int val;
    struct ListNode *next;
} Node, *ListNode;

/**
 * 链表逆置
 * @param node
 * 思路:
 * 原链表断开,后半部分结点一个个从头断开
 * 一个个加入到前半部分的头部
 */
void listReverse(ListNode node) {
    //指向第一段的虚拟头指针
    ListNode temp1 = (ListNode) malloc(sizeof(ListNode));
    //指向第二段的虚拟头指针
    ListNode temp2 = (ListNode) malloc(sizeof(ListNode));
    //处理头结点
    if (node == NULL) {
        return;
    }
    //只有1个结点
    if (node->next == NULL) {
        printf("%d", node->val);
        return;
    } else {
        //如果不止一个结点
        //temp1指向当前结点
        temp1->next = node;
        //如果有第三个结点
        if (node->next->next != NULL) {
            //下一个结点的指针指向第二个结点
            temp2->next = node->next;
            //第一个结点断开
            node->next = NULL;
        } else {
            //只有2个结点
            //第二个结点的下一个指向第一个结点
            node->next->next = node;
            //第一个结点断开
            node->next = NULL;
            return;
        }
    }
    //此时,整个链表分为两端
    //第一段为已逆序,第二段为未逆序
    //temp1指向第一段的头指针,temp2指向第二段的头指针

    //当第二段有下个结点
    ListNode temp = (ListNode) malloc(sizeof(ListNode));
    while (temp2->next->next != NULL) {
        //temp指向第二段的第二个结点
        temp->next = temp2->next->next;
        //指向第二段的头指针  temp2->next
        //它的next本来是指向第二段的第二个元素,现在断开,指向第一段的头指针指向的元素
        temp2->next->next = temp1->next;
        //第一段的虚拟头指针左移
        temp1->next = temp2->next;
        //第二段的虚拟头指针 替换 temp 重新指向第二段的第一个结点
        temp2->next = temp->next;
    }
    //当第二段没有下下个结点,即只有下一个结点时,这个结点的下一个直接指向第一段虚拟头指针指向的元素即可
    temp2->next->next = temp1->next;
}
void showPoint(ListNode node){
    while (node->next != NULL) {
        printf("%d", node->val);
        node = node->next;
    }
    //当没有下一个元素了
    printf("%d", node->val);
}

int main() {
    ListNode node5 = (ListNode) malloc(sizeof(ListNode));
    node5->val = 5;
    node5->next = NULL;
    ListNode node4 = (ListNode) malloc(sizeof(ListNode));
    node4->val = 4;
    node4->next = node5;
    ListNode node3 = (ListNode) malloc(sizeof(ListNode));
    node3->val = 3;
    node3->next = node4;
    ListNode node2 = (ListNode) malloc(sizeof(ListNode));
    node2->val = 2;
    node2->next = node3;
    ListNode node1 = (ListNode) malloc(sizeof(ListNode));
    node1->val = 1;
    node1->next = node2;
    listReverse(node1);
    showPoint(node5);
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值