本科学c 的时候学过链表,但是学的非常浅,现在又要重新回顾一下
按照惯例:
简单介绍一下链表:
链表
链表面试的时候非常重要的一种数据结构,链表的结构非常简单,是有指针把若干个节点连接成的链状结构,链表的创建,插入,查询使用都非常的渐变,代码量比较小。链表是一种动态的数据结构,他的操作需要对指针进行操作。
链表是一种常见的数据结构,是一种线性表,因为链表是一种动态的数据结构,所以,链表不是不固定长度的,她可以充分的利用计算机的内存空间,实现灵活的动态内存管理,但是缺失了数组随机读取的优点,意思是链表是一种不适合查找的动态数据结构,同时,链表增加了节点的指针域,空间开销比较大。
1 单向链表(single-Linkes List)
单向链表的结构:
单链表是链表中结构最简单的。一个单链表的节点(Node)分为两个部分,第一个部分(data)保存或者显示关于节点的信息,另一个部分存储下一个节点的地址。最后一个节点存储地址的部分指向空值。单向链表只可向一个方向遍历,一般查找一个节点的时候需要从第一个节点开始每次访问下一个节点,一直访问到需要的位置。而插入一个节点,对于单向链表,我们只提供在链表头插入,只需要将当前插入的节点设置为头节点,next指向原头节点即可。删除一个节点,我们将该节点的上一个节点的next指向该节点的下一个节点。
package 链表;
public class test {
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.add(0);
nm.print();
System.out.println("--------------del-------------");
nm.delete(3);
nm.print();
System.out.println("--------------find-------------");
System.out.println(nm.find(1));
System.out.println("---------updata--------------");
nm.updata(1, 444444);
nm.print();
System.out.println("----------insert----------");
nm.insert(5, 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);// 如果root为空的话就传data
} else {
root.addNode(data);//
}
}
// 删除节点
public void delete(int data) {
if (root == null)
return;
if (root.getData() == data) {
root = root.next;
} else {
root.deleteNode(data);
}
}
// 插入节点,向索引之前插入
public void insert(int index, int data) {
if (index < 0)
return;
currentindex = 0;
if (index == currentindex) {
Node newNode = new Node(data);
// root.next=newNode;//往后插入
newNode.next = root;// 向前插入
root = newNode;
} else {
root.insertNode(index, 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 updata(int olddata, int newdata) {
if (root == null)
return false;// 结束 也没有返回值
if (root.getData() == olddata) {
root.setData(newdata);
return true;
} else {
return root.updataNoede(olddata, newdata);
}
}
// 不想在类的外部被访问到,所以定义成私有的内部类
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 this.data;
}
// 添加节点
public void addNode(int data) {
if (this.next == null) {
this.next = new Node(data);
} else {
this.next.addNode(data);// 一个递归的方法调用
}
}
// 删除节点
public void deleteNode(int data) {
if (this.next != null) {
if (this.next.data == data) {
this.next = this.next.next;// 找到这个数据了, 就把这个node 节点往后移动,中间的相当于弹出
} else {
this.next.deleteNode(data);// 没找到,递归调用next再去deleteNode
}
}
}
// 输出所有节点
public void printNode() {
if (this.next != null) {
if (this.next.next != null) {
System.out.print(this.next.data + "->");
this.next.printNode();
} else {
System.out.println(this.next.data);
}
}
}
// 查找节点
public boolean findNode(int data) {
if (this.next != null) {
if (this.next.getData() == data) {// 如果找到了就返回true
return true;
} else {
return (this.next.findNode(data));
}
}
return false;
}
// 修改节点
public boolean updataNoede(int olddata, int newdata) {
if (this.next != null) {
if (this.next.getData() == olddata) {
this.next.setData(newdata);
return true;
} else {
return this.next.updataNoede(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);
}
}
}
}
链表和数组比较
数组适合做查找,遍历这样的存储和操作,固定长度
链表适合做插入和删除操作,长度不宜过长,否则会导致遍历性能下降,解决方案:双端链表。
每一种数据结构都有其适用的情境,各有利弊。要根据不同的情景来操作。