Java 单向链表模拟

链表是有序的列表
链表是以节点的方式来存储的,各个节点不一定是连续存储的
分为带头节点的链表和没有头节点的链表
头节点不存放具体数据

单向链表:
其中每一个节点包含一个存储数据的data,一个指向下一个节点的变量

class Team {
    int no;
    String leader;

    public Team(int no, String leader) {
        this.no = no;
        this.leader = leader;
    }

    @Override
    public String toString() {
        return "Team{" +
                "no=" + no +
                ", leader='" + leader + '\'' +
                '}';
    }
}

class TeamNode {
    Team team;
    TeamNode nextNode;

    public TeamNode(Team team) {
        this.team = team;
    }

    @Override
    public String toString() {
        return "TeamNode{" +
                "team=" + team +
                '}';
    }
}

class TeamNodeList {
    private TeamNode headNode = new TeamNode(null);

    //添加元素,找到链表最后一个元素,让最后一个元素的next节点指向新元素
    public void add(Team team) {
        TeamNode curNode = headNode;
        TeamNode teamNode = new TeamNode(team);
        while(curNode.nextNode != null) {
            curNode = curNode.nextNode;
        }
        curNode.nextNode = teamNode;
    }

    //按编号顺序添加元素,遍历链表,找到当前节点的下一个节点的编号大于新元素编号的当前节点
    //将新节点的next节点指向当前节点的下一个节点,当前节点的next节点指向新节点
    public void addByOrder(Team team) {
        TeamNode curNode = headNode;
        TeamNode teamNode = new TeamNode(team);
        while(curNode.nextNode != null) {
            if(curNode.nextNode.team.no > team.no) {
                break;
            }
            curNode = curNode.nextNode;
        }
        teamNode.nextNode = curNode.nextNode;
        curNode.nextNode = teamNode;
    }

    //根据编号修改节点内容
    //遍历链表找到编号相同的队伍数据,将内容设置为新队伍的数据
    public void update(Team team) {
        TeamNode curNode = headNode;
        while(curNode.nextNode != null) {
            if(curNode.nextNode.team.no == team.no) {
                break;
            }
            curNode = curNode.nextNode;
        }
        if(curNode.nextNode == null) {
            System.out.println("没有找到对应队伍");
            return;
        }
        curNode.nextNode.team.leader = team.leader;
    }

    //根据编号删除节点
    //遍历链表,找到删除节点,将删除节点前的节点的next节点指向删除节点的next节点
    public void deleteNode(int no) {
        TeamNode curNode = headNode;
        while(curNode.nextNode != null) {
            if(curNode.nextNode.team.no == no) {
                break;
            }
            curNode = curNode.nextNode;
        }
        if(curNode.nextNode == null) {
            System.out.println("没有找到对应队伍");
            return;
        }
        curNode.nextNode = curNode.nextNode.nextNode;
    }

    //遍历节点打印
    public void listNodes() {
        TeamNode curNode = headNode;
        while(curNode.nextNode != null) {
            System.out.println(curNode.nextNode.team);
            curNode = curNode.nextNode;
        }
    }

    //求单链表中有效节点的个数
    public void test1(TeamNode headNode) {
        TeamNode curNode = headNode;
        int len = 0;
        while(curNode.nextNode != null) {
            len++;
            curNode = curNode.nextNode;
        }
        System.out.println("有效节点有:" + len + "个");
    }

    //查找链表中倒数第k个节点
    public void test2(int k) {
        TeamNode curNode = headNode;
        int len = 0;
        while(curNode.nextNode != null) {
            len++;
            curNode = curNode.nextNode;
        }
        if( k > len) {
            System.out.println("超过链表长度");
            return;
        }
        curNode = headNode;
        for(int i = 0;i < len - k;i++) {
            curNode = curNode.nextNode;
        }
        System.out.println(curNode.team);
    }

    //单链表的反转
    public void test3() {
        TeamNode curNode = headNode.nextNode;
        TeamNode newHeadNode = new TeamNode(null);

        while(curNode != null) {
            TeamNode tmpNode = newHeadNode.nextNode; // 存放新头节点的next节点
            TeamNode nextNode = curNode.nextNode; // 存放当前节点的next节点

//            newHeadNode.nextNode = curNode; // 新头节点的next节点指向新元素节点
//            newHeadNode.nextNode.nextNode = tmpNode; //新头节点的next节点的next节点指向 上一次的新头节点的next节点,串起来
            //或
            curNode.nextNode = newHeadNode.nextNode;
            newHeadNode.nextNode = curNode;

            curNode = nextNode; //当前节点指向 下一个节点
        }
        headNode.nextNode = newHeadNode.nextNode; //原来的头节点的next节点指向新头节点的next节点,后面的元素都是反转后的

        listNodes();
    }

    //从尾到头打印单链表
    //使用stack,不用破坏原始链表结构
    public void test4() {
        Stack<Team> teamStack = new Stack<>();
        TeamNode curNode = headNode;
        while(curNode.nextNode != null) {
            teamStack.push(curNode.nextNode.team);
            curNode = curNode.nextNode;
        }

        while (! teamStack.isEmpty()) {
            System.out.println(teamStack.pop());
        }
    }
}

public class LinkedDemo {


    @Test
    public void test1() {
        TeamNodeList teamNodeList = new TeamNodeList();
        Team team1 = new Team(1, "山本元柳斎重国");
        Team team4 = new Team(4, "卯之花烈");
        Team team6 = new Team(6, "朽木白哉");
        Team team8 = new Team(8, "京乐春水");
        Team team10 = new Team(10, "日番谷冬狮郎");
        Team team13 = new Team(13, "浮竹十四郎");
        Team team13_new = new Team(13, "朽木露琪亚");

        teamNodeList.add(team1);
        teamNodeList.add(team4);
        teamNodeList.add(team6);
        teamNodeList.add(team13);


    }

    public static void main(String[] args) {
        TeamNodeList teamNodeList = new TeamNodeList();
        Team team1 = new Team(1, "山本元柳斎重国");
        Team team4 = new Team(4, "卯之花烈");
        Team team6 = new Team(6, "朽木白哉");
        Team team8 = new Team(8, "京乐春水");
        Team team10 = new Team(10, "日番谷冬狮郎");
        Team team13 = new Team(13, "浮竹十四郎");
        Team team13_new = new Team(13, "朽木露琪亚");

        teamNodeList.add(team1);
        teamNodeList.add(team4);
        teamNodeList.add(team6);
        teamNodeList.add(team13);

        System.out.println("============add============");
        teamNodeList.listNodes();
//        Team{no=1, leader='山本元柳斎重国'}
//        Team{no=4, leader='卯之花烈'}
//        Team{no=6, leader='朽木白哉'}
//        Team{no=13, leader='浮竹十四郎'}

        System.out.println("============addByOrder============");
        teamNodeList.addByOrder(team8);
        teamNodeList.listNodes();
//        Team{no=1, leader='山本元柳斎重国'}
//        Team{no=4, leader='卯之花烈'}
//        Team{no=6, leader='朽木白哉'}
//        Team{no=8, leader='京乐春水'}
//        Team{no=13, leader='浮竹十四郎'}

        System.out.println("============update============");
        teamNodeList.update(team13_new);
        teamNodeList.listNodes();
//        Team{no=1, leader='山本元柳斎重国'}
//        Team{no=4, leader='卯之花烈'}
//        Team{no=6, leader='朽木白哉'}
//        Team{no=8, leader='京乐春水'}
//        Team{no=13, leader='朽木露琪亚'}

        System.out.println("============deleteNode============");
        teamNodeList.deleteNode(4);
        teamNodeList.listNodes();
//        Team{no=1, leader='山本元柳斎重国'}
//        Team{no=6, leader='朽木白哉'}
//        Team{no=8, leader='京乐春水'}
//        Team{no=13, leader='朽木露琪亚'}

        System.out.println("============test3 反转============");
        teamNodeList.test3();
//        Team{no=13, leader='朽木露琪亚'}
//        Team{no=8, leader='京乐春水'}
//        Team{no=6, leader='朽木白哉'}
//        Team{no=1, leader='山本元柳斎重国'}

        System.out.println("============test4 从尾到头打印单链表============");
        teamNodeList.test4();
//        Team{no=1, leader='山本元柳斎重国'}
//        Team{no=6, leader='朽木白哉'}
//        Team{no=8, leader='京乐春水'}
//        Team{no=13, leader='朽木露琪亚'}
    }

}
上一篇:2022寒假训练week6


下一篇:习题6-4 使用函数输出指定范围内的Fibonacci数 (20 分)