数据结构与算法 :单链表

数据结构与算法 :单链表

1.单链表的概念

链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。

2.结构

每个结点包含data域,next域。

┌───┬───┐

│data │next │

└───┴───┘

data域–存放结点值的数据域

next域–存放结点的直接后继的地址(位置)的指针域(链域)

链表通过每个结点的链域将线性表的n个结点按其逻辑顺序链接在一起的,每个结点只有一个链域的链表称为单链表(Single Linked List)。

3.头指针head和终端结点

单链表中每个结点的存储地址是存放在其前趋结点next域中,而开始结点无前趋,故应设头指针head指向开始结点。链表由头指针唯一确定,单链表可以用头指针的名字来命名。

终端结点无后继,故终端结点的指针域为空,即NULL。

4.单链表的增删查改

利用水浒传英雄排行榜对人物进行增删查改操作

1). 添加(创建)

1.先创建一个头结点,作用是表示单链表的头

2.后面我们每添加一个结点,就直接加到链表的最后

遍历:

通过一个辅助变量遍历,帮助遍历整个链表

//定义单链表
class SingleLinkedList{
    //先初始化头节点
    private HeroCode head=new HeroCode(0,"","");

    //添加结点到链表
    public void add(HeroCode heroCode){
        //head结点不能动,需要辅助结点temp
        //思路:不考虑链表顺序时
        //1.找到当前链表的最后结点
        //2.将最后的结点的next指向新的结点
        HeroCode temp=head;
         while(true){
             if (temp.next==null){
                 break;
             }
             //将temp向后移
             temp=temp.next;
         }
        temp.next=heroCode;
    }
    //开始遍历
    public void list(){
          //判断链表是否为空
        if (head.next==null){
            System.out.println("链表为空");
            return;
        }
        //头结点不能动,需要辅助变量来遍历
        HeroCode temp=head.next;
        while (true){
            //判断链表是否到最后

            if (temp==null){
                break;
            }
            //输出结点
            System.out.println(temp);
            temp=temp.next;

        }

    }

}

2). 在添加英雄时,根据排名将英雄插入指定位置

按照顺序编号添加

1.首先找到新添加的结点的位置,通过辅助变量(指针)和遍历来搞定

2.新的结点.next=temp.next;

3.新temp.next=新的结点

//第二种添加英雄的方式,根据排名将英雄插入指定位置

    public void addByOrder(HeroCode heroCode){
//因为头节点不能动,所以用辅助变量来帮助找到添加位置
        //temp是位于添加位置的前一个结点
        HeroCode temp=head;
        boolean flag=false; //标志添加的编号是否存在

        while (true){
            if (temp.next==null){
                break;
            }
            if (temp.next.no>heroCode.no){//位置已找到,就在temp后面
                break;
            }
           else if (temp.next.no==heroCode.no){//说明添加的heroCode已经存在
                      flag=true;
                      break;

            }

            temp=temp.next;
        }

        //判断flag的值
        if(flag){  //不能添加,说明编号存在
            System.out.printf("英雄的编号%d存在,不能添加\n",heroCode.no);
        }else {
            heroCode.next=temp.next;
            temp.next=heroCode;
        }
    }

3).修改结点

1.先找到该节点,进行遍历

2.然后直接修改信息

//修改结点的信息,不改变no编号
    public void update(HeroCode newHeroCode){
        //判断链表为空
        if(head.next==null){
            System.out.println("链表为空");
            return;
        }
        //根据no编号,找到修改的结点
        //定义一个辅助变量
        HeroCode temp=head.next;
        boolean flag =false;//表示是否找到该结点
        while (true){
            if(temp==null){
                System.out.println("链表遍历完");
                break;
            }
            if (temp.no==newHeroCode.no){
                flag=true;
                break;
            }
            temp=temp.next;
        }

        //判断flag
        if(flag){
            temp.name= newHeroCode.name;
            temp.nickname=  newHeroCode.nickname;

        }else{
            System.out.printf("没有找到编号%d的结点,不能修改\n", newHeroCode.no);
        }
    }

4).删除结点

1.先要找到需要删除的结点的前一个结点的temp(辅助变量)

2.temp.next=temp.next.next;

3.被删除的结点,将不会有其他引用指向,会被垃圾回收机制回收

//删除结点
//思路:head结点不能动,需要一个辅助结点temp找到待删除结点的前一个结点
//在比较时,是temp.next.no和需要删除的结点的no比较
public void del(int no){
    HeroCode temp=head;
    boolean flag=false; //标志是否找到删除结点
        while (true){
            if (temp.next==null){
                break;    //说明遍历到最后
            } if (temp.next.no==no){
                //找到删除的结点
                flag=true;
                break;

            }
            temp=temp.next;


        }
    if (flag){
        temp.next=temp.next.next;

    }else{
        System.out.printf("删除的编号%d不存在\n",no);
    }
}

完整的代码如下

package 链表;

public class SingleLinkedListTest {
    public static void main(String[] args) {
//测试
//先创建结点
        HeroCode heroCode1=new HeroCode(1,"宋江","及时雨");
        HeroCode heroCode2=new HeroCode(2,"卢俊义","玉麒麟");
        HeroCode heroCode3=new HeroCode(3,"吴用","智多星");
        HeroCode heroCode4=new HeroCode(4,"林聪","豹子头");
//创建一个链表
 SingleLinkedList singleLinkedList=new SingleLinkedList();
 //添加
//        singleLinkedList.add(heroCode1);
//     singleLinkedList.add(heroCode4);
//    singleLinkedList.add(heroCode2);
//  singleLinkedList.add(heroCode3);



        singleLinkedList.addByOrder(heroCode1);
        singleLinkedList.addByOrder(heroCode4);
        singleLinkedList.addByOrder(heroCode2);
        singleLinkedList.addByOrder(heroCode3);
        //显示
        singleLinkedList.list();

        //修改信息

        HeroCode newHeroCode=new HeroCode(2,"小卢","玉麒麟");
        singleLinkedList.update(newHeroCode);
        System.out.println("--------------------");

        //在显示一次
        singleLinkedList.list();


        //删除一个结点
        singleLinkedList.del(1);
        System.out.println("删除过后的信息");
        singleLinkedList.list();
    }
}

//定义单链表
class SingleLinkedList{
    //先初始化头节点
    private HeroCode head=new HeroCode(0,"","");

    //添加结点到链表
    public void add(HeroCode heroCode){
        //head结点不能动,需要辅助结点temp
        //思路:不考虑链表顺序时
        //1.找到当前链表的最后结点
        //2.将最后的结点的next指向新的结点
        HeroCode temp=head;
         while(true){
             if (temp.next==null){
                 break;
             }
             //将temp向后移
             temp=temp.next;
         }
        temp.next=heroCode;
    }

//第二种添加英雄的方式,根据排名将英雄插入指定位置

    public void addByOrder(HeroCode heroCode){
//因为头节点不能动,所以用辅助变量来帮助找到添加位置
        //temp是位于添加位置的前一个结点
        HeroCode temp=head;
        boolean flag=false; //标志添加的编号是否存在

        while (true){
            if (temp.next==null){
                break;
            }
            if (temp.next.no>heroCode.no){//位置已找到,就在temp后面
                break;
            }
           else if (temp.next.no==heroCode.no){//说明添加的heroCode已经存在
                      flag=true;
                      break;

            }

            temp=temp.next;
        }

        //判断flag的值
        if(flag){  //不能添加,说明编号存在
            System.out.printf("英雄的编号%d存在,不能添加\n",heroCode.no);
        }else {
            heroCode.next=temp.next;
            temp.next=heroCode;
        }
    }
//修改结点的信息,不改变no编号
    public void update(HeroCode newHeroCode){
        //判断链表为空
        if(head.next==null){
            System.out.println("链表为空");
            return;
        }
        //根据no编号,找到修改的结点
        //定义一个辅助变量
        HeroCode temp=head.next;
        boolean flag =false;//表示是否找到该结点
        while (true){
            if(temp==null){
                System.out.println("链表遍历完");
                break;
            }
            if (temp.no==newHeroCode.no){
                flag=true;
                break;
            }
            temp=temp.next;
        }

        //判断flag
        if(flag){
            temp.name= newHeroCode.name;
            temp.nickname=  newHeroCode.nickname;

        }else{
            System.out.printf("没有找到编号%d的结点,不能修改\n", newHeroCode.no);
        }
    }

    //删除结点
    //思路:head结点不能动,需要一个辅助结点temp找到待删除结点的前一个结点
    //在比较时,是temp.next.no和需要删除的结点的no比较
    public void del(int no){
        HeroCode temp=head;
        boolean flag=false; //标志是否找到删除结点
            while (true){
                if (temp.next==null){
                    break;    //说明遍历到最后
                } if (temp.next.no==no){
                    //找到删除的结点
                    flag=true;
                    break;

                }
                temp=temp.next;


            }
        if (flag){
            temp.next=temp.next.next;

        }else{
            System.out.printf("删除的编号%d不存在\n",no);
        }
    }

    //开始遍历
    public void list(){
          //判断链表是否为空
        if (head.next==null){
            System.out.println("链表为空");
            return;
        }
        //头结点不能动,需要辅助变量来遍历
        HeroCode temp=head.next;
        while (true){
            //判断链表是否到最后

            if (temp==null){
                break;
            }
            //输出结点
            System.out.println(temp);
            temp=temp.next;

        }

    }

}

//定义一个HeroCode,每个HeroCode对象是一个结点
class HeroCode{
   public int no;
    public  String name;
    public String nickname;
public HeroCode next;
//构造器
public HeroCode(int no,String name ,String nickname){
    this.no=no;
    this.name=name;
    this.nickname=nickname;

}
//为了显示方法,重新toString
    @Override
    public String toString() {
        return "HeroNode[no="+ no +",name="+name+",nickname="+nickname+"]";
    }
}

你可能感兴趣的:(链表,数据结构,算法,java)