@[FAT-Remcal|从倔强青铜到最强王者]
SuperJava|数据结构之链表基础知识
知识要点
1 此知识内容是为了解框架底层而提前准备;(高级程序员必备)
2 链表概念:链表是一种线性表(纵向),但是不会按线性的顺序存储数据,用节点表示位置(数组使用"下标"表示位置);
3 内部类使用一个原则:谁拥有数据 (int data),谁来提供方法(),内部私有类中的属性只能自己对外开放访问权限;
4 数据结构操作操作助记:“增(add)、删(delete)、改(update)、查(find)”,插入节点(index);
4.1 添加节点:往链表的最后添加;
4.2 删除节点:删除当前节点的下一个节点(不能自杀);
4.3 查找节点:初始只能看见根节点(纵向),从头节点一个一个向后查找;
5 递归算法:是一种直接或者间接的调用自身算法的过程,递归算法使用内存消耗巨大,并且容易造成数据类型溢出(int),算法中必须设计好出口,不能无限调用;
6 递归算法扩展知识:递归算法执行时,内存的结构需要注意,每次调用方法进栈(带入局部变量),此方法栈中会生成局部变量,所以递归次数越多,在栈中生成的变量越多,所以消耗内存,有可能发生“栈内存溢出”;
7 内部类的使用就是一种功能的封装,使用内部类才可以声明为private;
应用场景
1 链表也是一种数据结构,但链表不同于数组,它没有下标,也没有明确的位置标识;
2 优点:链表数据结构的特性,适合频繁的“插入、删除”操作;
3 缺点:查找元素需要遍历,因此不支持随机查找,并且不宜过长,否则会导致遍历性能下降;
4 链表可以用于实现“栈数据结构”,或者“队列”,如邮件与微信的群发功能,链表知识内容可以作为“消息队列”的铺垫,需要留有印象;
Code:
/**
链表
一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,
而是在每一个节点里存到是下一个节点的指针(Pointer)。
链表与数组:线性数据结构
数组适合查找,遍历,固定长度
链表适合插入,删除,不宜过长,否则会导致遍历性能下降
*/
public class LinkedList{
public static void main(String[] args){
NodeManager nm = new NodeManager();
System.out.println("------add----------");
nm.add(5);
nm.add(4);
nm.add(3);
nm.add(2);
nm.add(1);
nm.print();
System.out.println("-------del---------");
nm.del(3);
nm.print();
System.out.println("-------find---------");
System.out.println(nm.find(1));
System.out.println("-------update---------");
nm.update(1,10);
nm.print();
System.out.println("-------insert---------");
nm.insert(1,20);
nm.print();
}
}
class NodeManager{
private Node root;//根节点
private int currentIndex = 0;//节点的序号,每次操作从0开始
//添加
public void add(int data){
if(root==null){
root = new Node(data);
}else{
root.addNode(data);
}
}
//删除
public void del(int data){
if(root==null)return;
if(root.getData()==data){
root = root.next;
}else{
root.delNode(data);
}
}
//打印所有
public void print(){
if(root!=null){
System.out.print(root.getData()+"->");
root.printNode();
System.out.println();
}
}
//查找是否存在节点
public boolean find(int data){
if(root==null)return false;
if(root.getData()==data){
return true;
}else{
return root.findNode(data);
}
}
//更新
public boolean update(int oldData,int newData){
if(root==null)return false;
if(root.getData()==oldData){
root.setData(newData);
return true;
}else{
return root.updateNode(oldData,newData);
}
}
//向索引之前插入
public void insert(int index,int data){
if(index<0)return;
currentIndex = 0;
if(index==currentIndex){
Node newNode = new Node(data);
newNode.next = root;
root = newNode;
}else{
root.insertNode(index,data);
}
}
private class Node{
private int data;
private Node next; //把当前类型作为属性
public Node(int data){
this.data = data;
}
public void setData(int data){
this.data = data;
}
public int getData(){
return data;
}
//添加节点
public void addNode(int data){
if(this.next==null){
this.next = new Node(data);
}else{
this.next.addNode(data);
}
}
//删除节点
public void delNode(int data){
if(this.next!=null){
if(this.next.data==data){
this.next = this.next.next;
}else{
this.next.delNode(data);
}
}
}
//输出所有节点
public void printNode(){
if(this.next!=null){
System.out.print(this.next.data+"->");
this.next.printNode();
}
}
//查找节点是否存在
public boolean findNode(int data){
if(this.next!=null){
if(this.next.data==data){
return true;
}else{
return this.next.findNode(data);
}
}
return false;
}
//修改节点
public boolean updateNode(int oldData,int newData){
if(this.next!=null){
if(this.next.data==oldData){
this.next.data = newData;
return true;
}else{
return this.next.updateNode(oldData,newData);
}
}
return false;
}
//插入节点
public void insertNode(int index,int data){
currentIndex++;
if(index==currentIndex){
Node newNode = new Node(data);
newNode.next = this.next;
this.next = newNode;
}else{
this.next.insertNode(index,data);
}
}
}
}