JAVA笔记:算法与数据结构【单链表】

背景:用JAVA实现单链表的所有操作(

目录

  1. 创建带头节点head的类SingleLinkedList.java
  2. 创建类SingleLinkdeListMan,用于实现对SingleLinkedlist的所有操作
  3. 创建头节点
  4. 添加节点方式一:直接添加在末尾
  5. 添加节点方式二:自动有序化(添加无序,但是会自动排序)
  6. 打印链表
  7. 指定有哪个头节点开始打印链表
  8. 修改链表节点属性(demo只改名字和绰号)
  9. 删除节点
  10. 统计节点数
  11. 查找倒数第K个节点
  12. 反转链表(改变链表结构)
  13. 反转打印(只打印,不改变链表结构)
  14. 合并两个有序的链表,合并之后依然有序

开始

  1. 创建带头节点head的类SingleLinkedList.java
public class SingleLinkedList {
    public int no;
    public String name;
    public String nickName;
    public SingleLinkedList next;

    public SingleLinkedList(int no, String name, String nickName) {
        this.no = no;
        this.name = name;
        this.nickName = nickName;
    }

    @Override
    public String toString() {
        return "SingleLinkedList{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickName='" + nickName + '\'' +
                '}';
    }
}

  1. 创建类SingleLinkdeListMan,用于实现对SingleLinkedlist的所有操作

  2. 创建头节点

 private SingleLinkedList head = new SingleLinkedList(0, "", "");


    public SingleLinkedList getHead() {
        return head;
    }

  1. 添加节点方式一:直接添加在末尾
public void add(SingleLinkedList heroNode) {
        SingleLinkedList temp = head;
        while (temp.next != null) {
            temp = temp.next;
        }
        temp.next = heroNode;
    }

  1. 添加节点方式二:自动有序化(添加无序,但是会自动排序)
public void addByOrder(SingleLinkedList heroNode) {
        SingleLinkedList temp = head;//临时节点
        boolean flag = false;//如果有这个排名,则添加失败,并给出提示
        while (true) {
            if (temp.next == null) {
                break;//说明只有头节点,直接添加新的节点
            }
            if (temp.next.no > heroNode.no) {
                System.out.println("插入节点位置已经找到");
                break;
            } else if (temp.next.no == heroNode.no) {
                flag = true;//标志节点已经存在
                break;
            }
            temp = temp.next;//节点后移
        }
        if (flag) {
            System.out.printf("已经存在重复的英雄编号:%d,添加失败......\n", heroNode.no);
        } else {
            heroNode.next = temp.next;
            temp.next = heroNode;
        }

    }
  1. 打印链表
 //显示链表
    public void showList() {
        if (head.next == null) {
            System.out.println("showList:链表为空。。。");
            return;
        }
        SingleLinkedList temp = head.next;
        while (temp != null) {
            System.out.println(temp);
            temp = temp.next;
        }
    }
  1. 指定有哪个头节点开始打印链表
//由头遍历
    public static void showListFromHead(SingleLinkedList head) {
        if (head.next == null) {
            System.out.println("showList:链表为空。。。");
            return;
        }
        SingleLinkedList temp = head.next;
        while (temp != null) {
            System.out.println(temp);
            temp = temp.next;
        }
    }

  1. 修改链表节点属性(demo只改名字和绰号)
public void update(SingleLinkedList newHeroNode) {
        if (head.next == null) {
            System.out.println("此链表为空。。。。。");
        }
        SingleLinkedList temp = head.next;
        boolean flag = false;//标记是否找到要修改的节点
        while (true) {
            if (temp == null) {
                break;//此时temp是最后一个节点
            }
            if (temp.no == newHeroNode.no) {
                System.out.println("找到节点");
                flag = true;
                break;
            }
            temp = temp.next;//节点后移
        }
        if (flag) {
            System.out.println("进行修改。。。。。。。。");
            temp.name = newHeroNode.name;
            temp.nickName = newHeroNode.nickName;
        } else {
            System.out.printf("不存在节点:%d........\n", newHeroNode.no);
        }
    }
  1. 删除节点
 //删除
    public void deleteNode(int no) {
        SingleLinkedList temp = head;
        boolean flag = false;//标记是否找到
        while (true) {
            if (temp.next == null) {//已经到最后一个节点
                break;
            }
            if (temp.next.no == no) {
                //找到
                System.out.println("找到节点。。。。");
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag) {
            temp.next = temp.next.next;
        } else {
            System.out.println("节点不存在。。。。。");
        }
    }

  1. 统计节点数
public static int countNode(SingleLinkedList head) {
        if (head.next == null) {
            System.out.println("countNode:链表为空...");
            return 0;
        }
        int length = 0;
        SingleLinkedList cur = head.next;//不统计头节点
        while (cur != null) {
            length++;
            cur = cur.next;
        }
        return length;

    }
  1. 查找倒数第K个节点
//查找倒数第K个节点,用lastIndex表示
    //0、编写一个方法,接收head节点,同时接收一个lastIndex
    //1、判断链表是否为空,为空则直接返回null
    //2、获取链表长度size=countNode
    //3、校验lastIndex值,lastIndex应该大于0小于等于ize
    //3、遍历链表size-lastIndex
    //4、返回节点

    public static SingleLinkedList getLastIndexNode(SingleLinkedList head, int lastIndex) {
        if (head.next == null) {
            return null;
        }
        int size = countNode(head);//获取链表长度size=countNode
        SingleLinkedList temp = head.next;
        if (lastIndex <= 0 || lastIndex > size) {
            System.out.println("lastIndex输入有误");
            return null;
        }
        for (int i = 0; i < size - lastIndex; i++) {
            temp = temp.next;
        }
        return temp;
    }
  1. 反转链表(改变链表结构)
 //反转链表
    public static void reverseNode(SingleLinkedList head) {
        if (head.next == null || head.next.next == null) {//链表为空或者链表只有一个节点
            System.out.println("链表为空或者链表只有一个节点,请直接打印");
            return;
        }
        SingleLinkedList newReverseNode = new SingleLinkedList(0, "", "");
        SingleLinkedList cur = head.next;//指向当前节点
        SingleLinkedList curNext = null;//指向cur节点的下一个节点,当cur取出节点后用来标记
        while (cur != null) {
            curNext = cur.next;//指向cur节点的下一个节点,当cur取出节点后用来标记
            cur.next = newReverseNode.next;//取出cur指向的节点,接到newReverseNode后面
            newReverseNode.next = cur;//让newReverseNode与后面的反转节点连通
            cur = curNext;//让cur指向下一个节点
        }
        head.next = newReverseNode.next;//让head重新作为反转链表的头节点
    }

  1. 反转打印(只打印,不改变链表结构)
 //反转打印
    public static void reversePrint(SingleLinkedList head) {
        if (head.next == null) {
            return;
        }
        SingleLinkedList cur = head.next;//临时变量
        Stack<SingleLinkedList> stack = new Stack<SingleLinkedList>();
        while (cur != null) {//入栈
            stack.push(cur);
            cur = cur.next;
        }
        while (stack.size() > 0) {
            System.out.println(stack.pop());//出栈
        }

    }

  1. 合并两个有序的链表,合并之后依然有序
//合并两个有序的链表,合并之后依然有序
    //newLinkNode,head1,head2
    //cur1,cur1Next,cur2,cur2Next
    //思路:
    //1、判断传递的两链表是否为空
    //2、创建一个新的链表newLinkNode,并同时创建它的尾指针lastNewLinkNode
    //3、创建临时指针temp1、temp2,用来标记原链表
    //4、根据编号比较大小,小的插入到newLinkNode后

    public SingleLinkedList transTwoLinkToNe(SingleLinkedList head1, SingleLinkedList head2) {
        if (head1.next == null) {
            return head2;//若head1为空,直接返回有序链表head2
        }
        if (head2.next == null) {
            return head1;
        }
        SingleLinkedList newLinkNode = null;//新的存储链表
        SingleLinkedList lastNewLinkNode = null;//新的存储链表的尾部指针
        SingleLinkedList temp1 = head1.next;//temp1指向head1的第一个有效节点(含头节点链表)
        SingleLinkedList temp2 = head2.next;
        while (temp1 != null && temp2 != null) {//当链表一个为空时退出遍历
            if (temp1.no <= temp2.no) {
                if (newLinkNode == null) {
                    newLinkNode = temp1;//初始化加载,让newLinkNode指向temp1
                } else {
                    lastNewLinkNode.next = temp1;//让尾指针指向新的临时节点
                }
                lastNewLinkNode = temp1;//初始化,并让尾指针后移指向temp1
                temp1 = temp1.next;//移动一次


            } else {
                if (newLinkNode == null) {
                    newLinkNode = temp2;
                } else {
                    lastNewLinkNode.next = temp2;
                }
                lastNewLinkNode = temp2;
                temp2 = temp2.next;

            }
        }
            if (temp1 != null) {//将剩余的节点插入完
                lastNewLinkNode.next = temp1;//直接将剩下的节点接上即可
            } else {
                lastNewLinkNode.next = temp2;
            }

        return newLinkNode;

    }
}

源码:SingleLinkedList.java

public class SingleLinkedList {
    public int no;
    public String name;
    public String nickName;
    public SingleLinkedList next;

    public SingleLinkedList(int no, String name, String nickName) {
        this.no = no;
        this.name = name;
        this.nickName = nickName;
    }

    @Override
    public String toString() {
        return "SingleLinkedList{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickName='" + nickName + '\'' +
                '}';
    }
}

源码:LinkedListMan.java

import java.util.Stack;

/**
 * @author GodLike
 * @create 2019-10-07-20:03
 */
public class LinkedListMan {
    //创建头节点
    private SingleLinkedList head = new SingleLinkedList(0, "", "");


    public SingleLinkedList getHead() {
        return head;
    }


    //添加节点
    public void add(SingleLinkedList heroNode) {
        SingleLinkedList temp = head;
        while (temp.next != null) {
            temp = temp.next;
        }
        temp.next = heroNode;
    }

    //显示链表
    public void showList() {
        if (head.next == null) {
            System.out.println("showList:链表为空。。。");
            return;
        }
        SingleLinkedList temp = head.next;
        while (temp != null) {
            System.out.println(temp);
            temp = temp.next;
        }
    }

    //由头遍历
    public static void showListFromHead(SingleLinkedList head) {
        if (head.next == null) {
            System.out.println("showList:链表为空。。。");
            return;
        }
        SingleLinkedList temp = head.next;
        while (temp != null) {
            System.out.println(temp);
            temp = temp.next;
        }
    }


    //第二种方式在添加英雄时,根据排名将英雄插入到指定位置(如果有这个排名,则添加失败,并给出提示)
    public void addByOrder(SingleLinkedList heroNode) {
        SingleLinkedList temp = head;//临时节点
        boolean flag = false;//如果有这个排名,则添加失败,并给出提示
        while (true) {
            if (temp.next == null) {
                break;//说明只有头节点,直接添加新的节点
            }
            if (temp.next.no > heroNode.no) {
                System.out.println("插入节点位置已经找到");
                break;
            } else if (temp.next.no == heroNode.no) {
                flag = true;//标志节点已经存在
                break;
            }
            temp = temp.next;//节点后移
        }
        if (flag) {
            System.out.printf("已经存在重复的英雄编号:%d,添加失败......\n", heroNode.no);
        } else {
            heroNode.next = temp.next;
            temp.next = heroNode;
        }

    }

    //修改
    public void update(SingleLinkedList newHeroNode) {
        if (head.next == null) {
            System.out.println("此链表为空。。。。。");
        }
        SingleLinkedList temp = head.next;
        boolean flag = false;//标记是否找到要修改的节点
        while (true) {
            if (temp == null) {
                break;//此时temp是最后一个节点
            }
            if (temp.no == newHeroNode.no) {
                System.out.println("找到节点");
                flag = true;
                break;
            }
            temp = temp.next;//节点后移
        }
        if (flag) {
            System.out.println("进行修改。。。。。。。。");
            temp.name = newHeroNode.name;
            temp.nickName = newHeroNode.nickName;
        } else {
            System.out.printf("不存在节点:%d........\n", newHeroNode.no);
        }
    }

    //删除
    public void deleteNode(int no) {
        SingleLinkedList temp = head;
        boolean flag = false;//标记是否找到
        while (true) {
            if (temp.next == null) {//已经到最后一个节点
                break;
            }
            if (temp.next.no == no) {
                //找到
                System.out.println("找到节点。。。。");
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag) {
            temp.next = temp.next.next;
        } else {
            System.out.println("节点不存在。。。。。");
        }
    }

    //统计有效节点数(不包括头节点)

    /**
     * @return 节点数
     */
    public static int countNode(SingleLinkedList head) {
        if (head.next == null) {
            System.out.println("countNode:链表为空...");
            return 0;
        }
        int length = 0;
        SingleLinkedList cur = head.next;//不统计头节点
        while (cur != null) {
            length++;
            cur = cur.next;
        }
        return length;

    }

    //查找倒数第K个节点,用lastIndex表示
    //0、编写一个方法,接收head节点,同时接收一个lastIndex
    //1、判断链表是否为空,为空则直接返回null
    //2、获取链表长度size=countNode
    //3、校验lastIndex值,lastIndex应该大于0小于等于ize
    //3、遍历链表size-lastIndex
    //4、返回节点

    public static SingleLinkedList getLastIndexNode(SingleLinkedList head, int lastIndex) {
        if (head.next == null) {
            return null;
        }
        int size = countNode(head);//获取链表长度size=countNode
        SingleLinkedList temp = head.next;
        if (lastIndex <= 0 || lastIndex > size) {
            System.out.println("lastIndex输入有误");
            return null;
        }
        for (int i = 0; i < size - lastIndex; i++) {
            temp = temp.next;
        }
        return temp;
    }


    //反转链表
    public static void reverseNode(SingleLinkedList head) {
        if (head.next == null || head.next.next == null) {//链表为空或者链表只有一个节点
            System.out.println("链表为空或者链表只有一个节点,请直接打印");
            return;
        }
        SingleLinkedList newReverseNode = new SingleLinkedList(0, "", "");
        SingleLinkedList cur = head.next;//指向当前节点
        SingleLinkedList curNext = null;//指向cur节点的下一个节点,当cur取出节点后用来标记
        while (cur != null) {
            curNext = cur.next;//指向cur节点的下一个节点,当cur取出节点后用来标记
            cur.next = newReverseNode.next;//取出cur指向的节点,接到newReverseNode后面
            newReverseNode.next = cur;//让newReverseNode与后面的反转节点连通
            cur = curNext;//让cur指向下一个节点
        }
        head.next = newReverseNode.next;//让head重新作为反转链表的头节点
    }





    //反转打印
    public static void reversePrint(SingleLinkedList head) {
        if (head.next == null) {
            return;
        }
        SingleLinkedList cur = head.next;//临时变量
        Stack<SingleLinkedList> stack = new Stack<SingleLinkedList>();
        while (cur != null) {//入栈
            stack.push(cur);
            cur = cur.next;
        }
        while (stack.size() > 0) {
            System.out.println(stack.pop());//出栈
        }

    }

    //合并两个有序的链表,合并之后依然有序
    //newLinkNode,head1,head2
    //cur1,cur1Next,cur2,cur2Next
    //思路:
    //1、判断传递的两链表是否为空
    //2、创建一个新的链表newLinkNode,并同时创建它的尾指针lastNewLinkNode
    //3、创建临时指针temp1、temp2,用来标记原链表
    //4、根据编号比较大小,小的插入到newLinkNode后

    public SingleLinkedList transTwoLinkToNe(SingleLinkedList head1, SingleLinkedList head2) {
        if (head1.next == null) {
            return head2;//若head1为空,直接返回有序链表head2
        }
        if (head2.next == null) {
            return head1;
        }
        SingleLinkedList newLinkNode = null;//新的存储链表
        SingleLinkedList lastNewLinkNode = null;//新的存储链表的尾部指针
        SingleLinkedList temp1 = head1.next;//temp1指向head1的第一个有效节点(含头节点链表)
        SingleLinkedList temp2 = head2.next;
        while (temp1 != null && temp2 != null) {//当链表一个为空时退出遍历
            if (temp1.no <= temp2.no) {
                if (newLinkNode == null) {
                    newLinkNode = temp1;//初始化加载,让newLinkNode指向temp1
                } else {
                    lastNewLinkNode.next = temp1;//让尾指针指向新的临时节点
                }
                lastNewLinkNode = temp1;//初始化,并让尾指针后移指向temp1
                temp1 = temp1.next;//移动一次


            } else {
                if (newLinkNode == null) {
                    newLinkNode = temp2;
                } else {
                    lastNewLinkNode.next = temp2;
                }
                lastNewLinkNode = temp2;
                temp2 = temp2.next;

            }
        }
            if (temp1 != null) {//将剩余的节点插入完
                lastNewLinkNode.next = temp1;//直接将剩下的节点接上即可
            } else {
                lastNewLinkNode.next = temp2;
            }

        return newLinkNode;

    }
}

测试Demo源码:

/**
 * @author GodLike
 * @create 2019-10-07-20:04
 */
public class Demo {
    public static void main(String[] args) {
        SingleLinkedList hero1 = new SingleLinkedList(1, "1", "1");
        SingleLinkedList hero3 = new SingleLinkedList(5, "5", "5");
        SingleLinkedList hero4 = new SingleLinkedList(4, "4", "4");
        SingleLinkedList hero2 = new SingleLinkedList(9, "9", "9");
        LinkedListMan addHero = new LinkedListMan();
        addHero.addByOrder(hero1);
        addHero.addByOrder(hero3);
        addHero.addByOrder(hero4);
       /* addHero.addByOrder(hero2);*/
        addHero.addByOrder(hero2);
        addHero.showList();

        SingleLinkedList hero5 = new SingleLinkedList(1, "1", "1");
        SingleLinkedList hero6 = new SingleLinkedList(3, "3", "3");
        SingleLinkedList hero7 = new SingleLinkedList(6, "6", "6");
        SingleLinkedList hero8 = new SingleLinkedList(2, "2", "2");
        LinkedListMan addHero2 = new LinkedListMan();
        addHero2.addByOrder(hero5);
        addHero2.addByOrder(hero6);
        addHero2.addByOrder(hero7);
        addHero2.addByOrder(hero8);
        addHero2.showList();
        //更新测试
        /*addHero.update(new SingleLinkedList(4,"linchong","baozitou"));
        addHero.showList();*/

        //删除测试
        /*addHero.deleteNode(2);
        addHero.deleteNode(1);
        addHero.showList();*/

        //获取有效节点数
        /* System.out.println(LinkedListMan.countNode(addHero.getHead()));*/

        //返回倒数第K个节点

       /* System.out.println(LinkedListMan.getLastIndexNode(addHero.getHead(),2));*/

        //反转测试
       /* System.out.println("..........");
       LinkedListMan.reverseNode(addHero.getHead());
       addHero.showList();*/

       //反转打印
        /*System.out.println("反转打印的结果是..........");
        LinkedListMan.reversePrint(addHero.getHead());
*/
       //合并测试
        LinkedListMan man=new LinkedListMan();
        SingleLinkedList a=man.transTwoLinkToNe(addHero.getHead(),addHero2.getHead());
        System.out.println("合并的结果是:..........");
        LinkedListMan.showListFromHead(a);
        System.out.println("链表一");
        addHero.showList();
        }

    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值