首先我们介绍什么是链表:链表是有序的列表,有如下几个特征:
(1)链表是以结点的方式来存储,是链式存储
(2)每个结点都包括data域,用来存放数据,next域指向下一个结点
(3)链表的各个结点不一定桉顺序连续存储
(4)链表分为,带头结点的链表和没有头结点的链表,根据实际需求来确定
单链表(带头结点)的逻辑结构如下:
头结点不存放具体的数据,它的作用就是表示单链表的表头,next域指向下一个node。
本篇文章主要讲单链表的创建(添加)和遍历,下一篇文章会讲删除和顺序排列,那么单链表的添加共分为三步:
(1)先创建一个head头结点,作用就是表示单链表的头
(2)每添加一个结点,就直接加入到链表的最后(不按大小顺序排列,只按照添加的顺序)
(3)通过一个辅助变量进行遍历整个链表
接下来我们就用一个实际的例子来帮助理解单链表的创建和遍历:
例子就是创建一个水浒传英雄单链表,包括排名,姓名,绰号,可以进行英雄的添加操作,添加完数据之后,可以遍历链表进行输出显示:
首先我们需要定义HeroNode:
//定义HeroNode,每个HeroNode对象就是一个结点class HeroNode{ public int no; public String name; public String nickname; public HeroNode next; //指向下一个结点 //构造器 public HeroNode(int no,String name,String nickname){ this.no = no; this.name = name; this.nickname = nickname; } //为了显示方法,重新写toString public String toString(){ return "HeroNode [no ="+no+"], name ="+ name +", nickname = " + nickname; }}
按照步骤写出添加结点到单链表:
//添加结点到单向链表 //思路,当不考虑编号顺序时 //1.找到当前链表的最后结点 //2.将最后结点的next域指向新的结点 public void add(HeroNode heroNode){ //因为head结点不能东,因此我们需要一个辅助变量 HeroNode temp = head; //遍历链表 while(true){ //找到链表的最后 if(temp.next ==null){ break; } //如果没有找到,就将temp后移 temp = temp.next; } //当推出while循环时,temp就指向链表的最后 temp.next = heroNode; }
最后遍历整个链表:
//显示链表【遍历】 public void list(){ //判断链表是否为空 if(head.next == null){ System.out.println("链表为空"); return; } //因为头结点不能动,因此需要一个辅助变量 HeroNode temp = head.next; while(true){ //判断是否到链表最后 if(temp ==null){ break; } //输出结点信息 System.out.println(temp); //将next后移,不然变成死循环 temp = temp.next; } }
写完之后,可以用例子在主函数中进行测试:
/** To change this license header, choose License Headers in Project Properties.* To change this template file, choose Tools | Templates* and open the template in the editor.*/package linkedlist;/**** @author Administrator*/public class SingleLinkedListDemo {public static void main(String[] args){//测试//先创建结点HeroNode hero1 = new HeroNode(1,"宋江","及时雨");HeroNode hero2 = new HeroNode(2,"卢俊义","玉麒麟");HeroNode hero3 = new HeroNode(3,"智多星","吴用");//创建链表SingleLinkedList singleLinkedList = new SingleLinkedList();singleLinkedList.add(hero1);singleLinkedList.add(hero2);singleLinkedList.add(hero3);//显示singleLinkedList.list();}}//定义SingleLinkedList 管理我们的英雄class SingleLinkedList{//先初始化一个头结点,头结点不要动private HeroNode head = new HeroNode(0,"","");//添加结点到单向链表//思路,当不考虑编号顺序时//1.找到当前链表的最后结点//2.将最后结点的next域指向新的结点public void add(HeroNode heroNode){//因为head结点不能东,因此我们需要一个辅助变量HeroNode temp = head;//遍历链表while(true){//找到链表的最后if(temp.next ==null){break;}//如果没有找到,就将temp后移temp = temp.next;}//当推出while循环时,temp就指向链表的最后temp.next = heroNode;}//显示链表【遍历】public void list(){//判断链表是否为空if(head.next == null){System.out.println("链表为空");return;}//因为头结点不能动,因此需要一个辅助变量HeroNode temp = head.next;while(true){//判断是否到链表最后if(temp ==null){break;}//输出结点信息System.out.println(temp);//将next后移,不然变成死循环temp = temp.next;}}}//定义HeroNode,每个HeroNode对象就是一个结点class HeroNode{public int no;public String name;public String nickname;public HeroNode next; //指向下一个结点//构造器public HeroNode(int no,String name,String nickname){this.no = no;this.name = name;this.nickname = nickname;}//为了显示方法,重新写toStringpublic String toString(){return "HeroNode [no ="+no+"], name ="+ name +", nickname = " + nickname;}}
添加完之后,运行程序,运行结果如下:
正确显示,不过如果我们在HeroNode1和HeroNode2之间添加4,那么该链表不会按照1-2-4的顺序显示,而是会按照1-4-2的添加顺序显示,在下一篇文章中,我们会一起学习单链表的顺序排列以及删除的操作。