链表属于数据结构中的基本操作。
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。
class Node //建立节点类,节点中保存数据和下一个对象
{
//封装属性
private String data; //建立数据,可以是任何数据类型
private Node next; //作为连接的下一个对象
//构造方法
public Node(String data)
{
this.data = data;
}
//属性的获取和设置方法
public void setData(String data)
{
this.data = data;
}
public String getData()
{
return this.data;
}
public void setNext(Node next)
{
this.next = next;
}
public Node getNext()
{
return this.next;
}
}
public class TestChain
{
public static void main(String [] args)
{
//建立节点
Node root = new Node("火车头");
Node n1 = new Node("车厢A");
Node n2 = new Node("车厢B");
Node n3 = new Node("车厢C");
//建立节点的关系
root.setNext(n1);
n1.setNext(n2);
n2.setNext(n3);
//打印出这种关系
print(root);
}
public static void print(Node node)
{
if (node != null) //如果该节点存在即打印
{
System.out.println(node.getData());
if (node.getNext() != null) //同时指向下一个节点
{
print(node.getNext());
}
}
}
}
结果
class Node //建立节点类,节点中保存数据和下一个对象
{
//封装属性
private String data; //建立数据,可以是任何数据类型
private Node next; //作为连接的下一个对象
//构造方法
public Node(String data)
{
this.data = data;
}
//属性的获取和设置方法
public void setData(String data)
{
this.data = data;
}
public String getData()
{
return this.data;
}
public void setNext(Node next)
{
this.next = next;
}
public Node getNext()
{
return this.next;
}
}
Node
类不变,他本身作为数据的载体出现,应该有程序自己控制。
现在好比有了一些要插入的数据(一群人),应该有一个来发号命令,这个类定义为
Link
。
链表操作中的根节点最重要,就想找到队伍的对头一样。第一个保存的元素为根节点。
用户增加数据,不关心Node,只关心数据(属性)。用户通过方法增加数据,必须由程序将数据封装成节点,使用Node的构造方法实现,否则无法完成next的引用问题。
在增加数据变为节点之后,首先判断该操作(link)是否有根节点,没有的话,就把增加的节点赋值到根节点,否则,节点自己动作,找到合适的位置。那么如何找到合适的位置呢?
首先,判断当前节点指向的next是否为空。空则表明新节点放在当前节点后面即可;否则,说明当前节点还指向下一个节点,用下一个节点来递归调用该方法。
案例:
class Node //建立节点类,节点中保存数据和下一个对象
{
//封装属性
private String data; //建立数据,可以是任何数据类型
private Node next; //作为连接的下一个对象
//构造方法
public Node(String data)
{
this.data = data;
}
//属性的获取和设置方法
public void setData(String data)
{
this.data = data;
}
public String getData()
{
return this.data;
}
public void setNext(Node next)
{
this.next = next;
}
public Node getNext()
{
return this.next;
}
//新节点找到合适的位置
public void addNode(Node newnode)
{
if (this.getNext() == null) //当前节点指向空,则可以把新节点排在这
{
this.setNext(newnode);
}else
{
this.getNext().addNode(newnode);
}
}
public void printNode()
{
System.out.println(this.getData()); //输出当前的数据
if (this.getNext() != null) //还有下一个节点
{
this.getNext().printNode();
}
}
}
class Link //链表操作类
{
private Node root; //定义根节点
public void add(String data) //增加数据,需要把数据变为节点
{
Node newnode = new Node(data);
if (this.root == null) //根节点为空
{
this.root = newnode;
}else
{
this.root.addNode(newnode);
}
}
public void print() //输出的全部数据
{
if (this.root != null)
{
this.root.printNode();
}
}
}
public class TestChain
{
public static void main(String [] args)
{
Link link = new Link();
String root = "火车头";
String n1 = "车厢1";
String n2 = "车厢2";
String n3 = "车厢3";
link.add(root);
link.add(n1);
link.add(n2);
link.add(n3);
link.print();
}
}
结果:
解释:
public void add(String data) //增加数据,需要把数据变为节点
{
Node newnode = new Node(data);
if (this.root == null) //根节点为空
{
this.root = newnode;
}else
{
this.root.addNode(newnode);
}
}
首先,Node newnode = new Node(data);把增加的属性封装为节点;其次判断this.root是否为空,如果根节点为空,新节点即为根节点;否则要调用Node类进行增加节点。
在Node类中,
if (this.getNext() == null) //当前节点指向空,则可以把新节点排在这
{
this.setNext(newnode);
}else
{
this.getNext().addNode(newnode);
}
首先判断当前节点的指向是否为空,如果是空说明新加入的节点可以直接链接到当前节点;否则要用下一个节点再次递归调用这一函数,找到合适位置
以上的这一切都归功于this关键字的操作,this代表的当前对象,那个对象调用了方法this就代表他。
class Node //建立节点类,节点中保存数据和下一个对象
{
//封装属性
private String data; //建立数据,可以是任何数据类型
private Node next; //作为连接的下一个对象
//构造方法
public Node(String data)
{
this.data = data;
}
//属性的获取和设置方法
public void setData(String data)
{
this.data = data;
}
public String getData()
{
return this.data;
}
public void setNext(Node next)
{
this.next = next;
}
public Node getNext()
{
return this.next;
}
//新节点找到合适的位置
public void addNode(Node newnode)
{
if (this.getNext() == null) //当前节点指向空,则可以把新节点排在这
{
this.setNext(newnode);
}else
{
this.getNext().addNode(newnode);
}
}
//类中查找数据
public boolean containsNode(String data)
{
if (this.getData().equals(data)) //当前相等
{
return true;
}
else if (this.getNext() == null) //找完了
{
return false;
}
else //还要继续找
{
return this.getNext().containsNode(data);
}
}
//类中打印数据
public void printNode()
{
System.out.println(this.getData()); //输出当前的数据
if (this.getNext() != null) //还有下一个节点
{
this.getNext().printNode();
}
}
}
class Link //链表操作类
{
private Node root; //定义根节点
public void add(String data) //增加数据,需要把数据变为节点
{
Node newnode = new Node(data);
if (this.root == null) //根节点为空
{
this.root = newnode;
}else
{
this.root.addNode(newnode);
}
}
public void print() //输出的全部数据
{
if (this.root != null)
{
this.root.printNode();
}
}
public boolean contains(String data) //定义查找数据的方法
{
if (this.root == null && data == null && "".equals(data))
{
return false; //不用判断
}
return this.root.containsNode(data); //否则调用Node类中的查找
}
}
public class TestChain
{
public static void main(String [] args)
{
Link link = new Link();
String root = "火车头";
String n1 = "车厢1";
String n2 = "车厢2";
String n3 = "车厢3";
link.add(root);
link.add(n1);
link.add(n2);
link.add(n3);
link.print();
System.out.println(link.contains("火车头1"));
}
}
结果:
能查找就能删除,因为删除之前必须保证删除的节点存在。删除节点就是空出节点的过程。在删除的过程中注意是否是根节点,如果是根节点,不同节点的删除方式不同。
案例:
class Node //建立节点类,节点中保存数据和下一个对象
{
//封装属性
private String data; //建立数据,可以是任何数据类型
private Node next; //作为连接的下一个对象
//构造方法
public Node(String data)
{
this.data = data;
}
//属性的获取和设置方法
public void setData(String data)
{
this.data = data;
}
public String getData()
{
return this.data;
}
public void setNext(Node next)
{
this.next = next;
}
public Node getNext()
{
return this.next;
}
//新节点找到合适的位置
public void addNode(Node newnode)
{
if (this.getNext() == null) //当前节点指向空,则可以把新节点排在这
{
this.setNext(newnode);
}else
{
this.getNext().addNode(newnode);
}
}
//类中查找数据
public boolean containsNode(String data)
{
if (this.getData().equals(data)) //当前相等
{
return true;
}
else if (this.getNext() == null) //找完了
{
return false;
}
else //还要继续找
{
return this.getNext().containsNode(data);
}
}
//类中删除数据
public void deleteNode(String data)
{
if (this.getNext().getData().equals(data))
{
this.setNext(this.getNext().getNext());
}else if (this.getNext().getNext() !=null)
{
this.getNext().deleteNode(data);
}
}
//类中打印数据
public void printNode()
{
System.out.println(this.getData()); //输出当前的数据
if (this.getNext() != null) //还有下一个节点
{
this.getNext().printNode();
}
}
}
class Link //链表操作类
{
private Node root; //定义根节点
public void add(String data) //增加数据,需要把数据变为节点
{
Node newnode = new Node(data);
if (this.root == null) //根节点为空
{
this.root = newnode;
}else
{
this.root.addNode(newnode);
}
}
public void print() //输出的全部数据
{
if (this.root != null)
{
this.root.printNode();
}
}
public boolean contains(String data) //定义查找数据的方法
{
if (this.root == null && data == null && "".equals(data))
{
return false; //不用判断
}
return this.root.containsNode(data); //否则调用Node类中的查找
}
//删除
public void delete(String data)
{
if (this.contains(data)) //要删除的节点是存在的
{
if (this.root.getData().equals(data)) //说明要删除的内容是根节点,则根赋值为后面的节点
{
this.root = this.root.getNext();
} else
{
this.root.deleteNode(data);
}
}
}
}
public class TestChain
{
public static void main(String [] args)
{
Link link = new Link();
String root = "火车头";
String n1 = "车厢1";
String n2 = "车厢2";
String n3 = "车厢3";
link.add(root);
link.add(n1);
link.add(n2);
link.add(n3);
link.print();
System.out.println(link.contains("火车头1"));
link.delete("车厢3");
link.delete("车厢1");
System.out.println("删除之后的结果:");
link.print();
}
}
结果:
这里的删除要先用查找进行判断,具体过程不再解释。
核心:this关键字的使用,引用传递。
祝大家健健康康,快快乐乐。