一、链表的概念
链表属于一种数据结构,链表可以保存多个数据,以字节的形式出现,每个字节都可以保存数据,而且每个节点除了可以保存数据之外还必须有对下一个节点的引用。
链表是后面的HashMap 的实现原理之一,是HashMap的基础。
Demo:定义节点
package com.sun;
class Node<T>{
private T data;
private Node nextNode;
public Node(){
}
public Node(T data){
this.data=data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Node getNextNode() {
return nextNode;
}
public void setNextNode(Node nextNode) {
this.nextNode = nextNode;
}
}
Demo:在主方法中使用节点
public class Test {
public static void main(String[] args) {
//创建出节点
Node<String> root=new Node<String >("火車頭");
Node<String> n1=new Node<String >("车厢A");
Node<String> n2=new Node<String >("车厢B");
Node<String> n3=new Node<String >("车厢C");
//维护节点之间的关系
root.setNextNode(n1);
n1.setNextNode(n2);
n2.setNextNode(n3);
//输出节点数据
Node<String> cuurentNode=root;
while(cuurentNode!=null){
System.out.print(cuurentNode.getData()+"--->");
cuurentNode=cuurentNode.getNextNode();
}
}
}
以上是使用while输出数据,那么最好的方式不是while循环而是递归输出。
Demo:递归输出
public class Test {
public static void main(String[] args) {
//创建出节点
Node<String> root=new Node<String >("火車頭");
Node<String> n1=new Node<String >("车厢A");
Node<String> n2=new Node<String >("车厢B");
Node<String> n3=new Node<String >("车厢C");
//维护节点之间的关系
root.setNextNode(n1);
n1.setNextNode(n2);
n2.setNextNode(n3);
//调用递归方法输出节点数据
print(root);
}
/**
* 递归输出节点数据
* @param currentNode
*/
public static void print(Node currentNode){
if(currentNode==null){
return ;
}
System.out.print(currentNode.getData()+"--->");
print(currentNode.getNextNode());
}
}
二、链表的完善
在上节课中我们说过了客服端不能出现复杂的操作,于是需要将链表的相关操作进行封装,不要在主方法中出现。
需要使用一个中间类来维护客户端和节点之间的交互,和二叉树很类似,节点是被封装到一个 BinaryTree 中了,那么这个外部类BinayTree 就是节点和客户端之间的一个中间类,客户端不能直接操作节点的类,而是通过BinaryTree类去操作。
Demo:需要一个中间类维护客户端和Node 节点的操作关系
class Node<T>{
private T data;
private Node nextNode;
public Node(){
}
public Node(T data){
this.data=data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Node getNextNode() {
return nextNode;
}
public void setNextNode(Node nextNode) {
this.nextNode = nextNode;
}
//添加节点数据
public void addNewNode(Node<T> newNode){
//判断当前节点的下一个节点是否为null
if(this.nextNode==null){
this.nextNode=newNode;
}else{
this.nextNode.addNewNode(newNode);
}
}
//输出节点的数据
public void printNode(){
System.out.println(this.data);
if(this.nextNode!=null){
this.nextNode.printNode();
}
}
}
//定义出Link类
class Link<T>{
private Node<T> root;//表示链表的根节点
int foot=0;// 用来记录节点的下标
/**
* Link中的添加数据的方法
* @param data
*/
public void add(T data){
Node<T> newNode=new Node<T>(data);
if(this.root==null){
this.root=newNode;
}else{
this.root.addNewNode(newNode);
}
}
/**
* 输出数据
*/
public void print(){
if(this.root==null){
return ;
}else{
this.root.printNode();
}
}
}
public class Test {
public static void main(String[] args) {
//添加数据
Link<String> link=new Link<String>();
link.add("JavaScript开发大全");
link.add("数据库从删库到跑路");
link.add("Java从入门到放弃");
link.add("毛泽东思想概论");
//输出数据
link.print();
}
}
将Node 设置为内部类
上面我们定义了Node类和Link类,Link的本质作用是将Node 和客户端之间的数据交互操作封装隐藏了,但是严格的做法不能在Link 类之外访问 Node类,也就是要让 Node类依赖于 Link类,但是此时我们还可以在客户端直接访问 Node类定义为 Link 类的私有内部类,这样的好处是什么呢?
好处:
让Node 类依赖 Link 的存在
内部类可以很方便的访问外部类的私有属性
Demo:将Node 定义为内部类
package com.sun;
//定义出Link类
class Link<T>{
private class Node<T>{ //定义了内部类
private T data;
private Node nextNode;
public Node(){
}
public Node(T data){
this.data=data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Node getNextNode() {
return nextNode;
}
public void setNextNode(Node nextNode) {
this.nextNode = nextNode;
}
//添加节点数据
public void addNewNode(Node<T> newNode){
//判断当前节点的下一个节点是否为null
if(this.nextNode==null){
this.nextNode=newNode;
}else{
this.nextNode.addNewNode(newNode);
}
}
//输出节点的数据
public void printNode(){
System.out.println(this.data);
if(this.nextNode!=null){
this.nextNode.printNode();
}
}
}
//以下代码是外部类中的代码
private Node<T> root;//表示链表的根节点
int foot=0;// 用来记录节点的下标
/**
* Link中的添加数据的方法
* @param data
*/
public void add(T data){
Node<T> newNode=new Node<T>(data);
if(this.root==null){
this.root=newNode;
}else{
this.root.addNewNode(newNode);
}
}
/**
* 输出数据
*/
public void print(){
if(this.root==null){
return ;
}else{
this.root.printNode();
}
}
}
public class Test {
public static void main(String[] args) {
//添加数据
Link<String> link=new Link<String>();
link.add("JavaScript开发大全");
link.add("数据库从删库到跑路");
link.add("Java从入门到放弃");
link.add("毛泽东思想概论");
//输出数据
link.print();
}
}
Demo:取得链表的长度
package com.sun;
//定义出Link类
class Link<T>{
private class Node<T>{ //定义了内部类
private T data;
private Node nextNode;
public Node(){
}
public Node(T data){
this.data=data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Node getNextNode() {
return nextNode;
}
public void setNextNode(Node nextNode) {
this.nextNode = nextNode;
}
//添加节点数据
public void addNewNode(Node<T> newNode){
//判断当前节点的下一个节点是否为null
if(this.nextNode==null){
this.nextNode=newNode;
}else{
this.nextNode.addNewNode(newNode);
}
}
//输出节点的数据
public void printNode(){
System.out.println(this.data);
if(this.nextNode!=null){
this.nextNode.printNode();
}
}
}
//以下代码是外部类中的代码>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
private Node<T> root;//表示链表的根节点
private int count=0;//保存节点个数(链表长度)
int foot=0;// 用来记录节点的下标
/**
* Link中的添加数据的方法
* @param data
*/
public void add(T data){
Node<T> newNode=new Node<T>(data);
if(this.root==null){
this.root=newNode;
}else{
this.root.addNewNode(newNode);
}
this.count++;
}
/**
* 输出数据
*/
public void print(){
if(this.root==null){
return ;
}else{
this.root.printNode();
}
}
/**
* 取得链表长度
* @return
*/
public int size(){
return this.count;
}
}
public class Test {
public static void main(String[] args) {
//添加数据
Link<String> link=new Link<String>();
link.add("JavaScript开发大全");
link.add("数据库从删库到跑路");
link.add("Java从入门到放弃");
link.add("毛泽东思想概论");
//输出数据
System.out.println("链表长度是:"+link.size());
}
}
Demo:判断链表是否为空
/**
* 判断链表是否为空
* @return 如果为空返回 true 否则就是返回false
*/
public boolean isEmpty(){
return this.count==0;
}
在外部类中增加的方法