一、概念
单向链表是一种简单数据结构,由多个节点构成,每个节点里面保存了节点中的数据和指向下一个节点的引用,链表的第一个节点被称为根节点(root)或头节点(head)
二、使用Java实现基本结构
需要一个Node类和一个Link类,Node类中存放Node中保存的数据和下一个Node的指向,Link类中保存root节点。
1 class Node { 2 private String data; 3 private Node next; 4 public Node(String data) { 5 this.data = data; 6 } 7 public String getData(){ 8 return data; 9 } 10 public void setNext(Node node) { 11 this.next = node; 12 } 13 public Node getNext() { 14 return next; 15 } 16 public void addNode(Node newNode){ //增加节点 17 if(this.next == null){ 18 this.next = newNode; 19 }else{ 20 //当前节点不为空,则用当前节点的下一个去继续保存 21 this.next.addNode(newNode); 22 } 23 } 24 public void printNode(){ 25 System.out.println(this.data); 26 if(this.next != null) 27 this.next.printNode(); 28 } 29 } 30 class List { 31 private Node root; 32 public void add(String data){ //增加数据 33 Node newNode = new Node(data); 34 if( this.root == null){ 35 this.root = newNode; 36 }else{ 37 this.root.addNode(newNode); 38 } 39 } 40 }
以上代码实现了链表的基本结构,和Link中的add()(以String对象为例子)方法,但是上面代码中Node类可以直接被外部访问,我们希望外部对链表的操作都通过Link类进行,Node类对外部隐藏,可以使用内部类来实现。
1 class Link{ 2 private class Node{ 3 private String data; //节点中要保存的数据 4 private Node next; //设置指向下一个节点 5 public Node(String data){ //构造方法保存数据 6 this.data = data; 7 } 8 public void addNode(Node newNode){ //将新节点添加到已有节点后 9 if(this.next == null){ //判断当前节点是否为最后一个节点 10 this.next = newNode; //如果是最后一个节点,则用当前节点指向新节点 11 }else{ 12 this.next.addNode(newNode); //否则向后继续保存 13 } 14 } 15 public boolean containsNode(String data){ //查询节点 16 if(data.equals(this.data)){ //找到内容,返回true 17 return true; 18 }else { 19 if (this.next != null){ //存在后续节点,继续 查找 20 this.next.containsNode(data); 21 }else{ 22 return false; //不存在后续节点,没找到 23 } 24 } 25 return false; 26 } 27 public String getNode(int index){ //根据索引查询节点 28 //将节点编号与索引进行比较,相等则返回当前节点中的数据,不相等则找下一个编号 29 if(Link.this.foot++ == index){ 30 return this.data; 31 }else{ 32 return this.next.getNode(index); 33 } 34 } 35 public void setNode(int index , String data){ //根据索引修改Node的内容 36 if(Link.this.foot ++ == index){ //找到对象Node 37 this.data = data; //修改data的值 38 }else{ 39 this.next.setNode(index, data); //继续判断下一个节点 40 } 41 } 42 public void removeNode(Node previous, String data){ 43 if(data.equals(this.data)){ 44 previous.next = this.next; 45 }else{ 46 this.next.removeNode(this,data); 47 } 48 } 49 public void toArrayNode(){ //将节点中数据转换成数组中的值 50 Link.this.refArray[Link.this.foot++] = this.data; 51 if(this.next != null){ //存在后续节点继续存放 52 this.next.toArrayNode(); 53 } 54 } 55 56 } 57 //==========================上面为Node节点================= 58 private Node root; //定义链表中的根节点 59 private int count = 0; //统计节点个数 60 private int foot = 0; //表示Node元素编号 61 private String[] refArray; //对象数组,用来存放各个节点的值 62 public void add(String data){ //链表中添加数据 63 if(data == null){ //为了简便,暂且设置不保存null值 64 return ; 65 } 66 Node newNode = new Node(data); //实例化一个Node节点来保存数据 67 if(this.root == null){ //判断是否存在root节点 68 this.root = newNode; //不存在则将当前节点设置为root节点 69 }else{ 70 this.root.addNode(newNode); //存在root节点则将新节点添加到链表后面 71 } 72 this.count ++ ; //保存成功count++ 73 74 } 75 public int size(){ //取得节点个数 76 return this.count; 77 } 78 public boolean isEmpty(){ //判断空链表 79 //return this.count == 0; 80 return this.root == null; 81 } 82 public boolean contains(String data){ //查找数据 83 if(data == null || this.root == null){ //没有要查数据或根节点没保存数据 84 return false ; 85 } 86 return this.root.containsNode(data); 87 } 88 public String get(int index){ 89 if(index > this.count){ //表示索引超出查询范围,没有数据 90 return null; 91 } 92 this.foot = 0; //每次查询都是从前往后查找 93 return this.root.getNode(index); 94 } 95 public void set(int index,String data){ //修改指定编号节点的内容 96 if(index > this.count){ 97 return ; //超出范围无法修改 98 } 99 this.foot = 0; //设置foot属性的内容 100 this.root.setNode(index,data); 101 } 102 public void remove(String data){ //移除指定数据 103 if(this.contains(data)){ //判断链表中是否存在指定数据 104 if(data.equals(this.root.data)){ //判断要删除的数据是否是root中数据 105 this.root = this.root.next; //移除root元素 106 }else{ 107 //继续判断下一个元素 108 this.root.next.removeNode(this.root, data); 109 } 110 } 111 this.count--; //删除一个节点,链表长度减一 112 } 113 public String[] toArray(){ 114 if(this.root == null){ 115 return null; 116 } 117 this.foot = 0; //初始化root 118 this.refArray = new String[this.count]; 119 this.root.toArrayNode(); //调用Node类中方法将每个节点数据添加到数组 120 return refArray; 121 } 122 }
以上代码将Node类作为Link类的内部类来实现单向链表,
public void add(String data){}:向链表中添加数据,需要为Link增加一个Node,这里将Node添加到Link的最后,每成功增加一个数据,count自增记录Link中Node的个数;
public int size(){}:统计Link中Node元素的个数;
public boolean isEmpty(){}:判断空链表,有两种判断方式,一种是判断root节点是否为空,另一种是判断节点个数是否为0;
public boolean contains(String data){}:查找Link中是否存在指定数据,从root节点开始一次判断每个Node中的数据是否符合;
public String get(int index){}:根据索引查找Link中对应的数据,索引从0开始;
public void set(int index,String data){}:根据索引修改Link中对应的数据内容;
public void remove(String data){}:根据指定内容移除Link中对应的Node,成功移除节点个数减1;
public String[] toArray(){}:将Link转换成对象数组,数组长度为Link中Node的个数;