因为数组一旦定义以后,长度便固定。在实际应用中并不方便,所以产生了链表。Java中的链表也分为双向链表和单向链表。双向链表在随机访问上,比多链表更有优势。
单链表实现:
class Node{
private Object data; //真实保存的数据
private Node next; //指向的下一个节点
public Node(Object data) {
this.data = data;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
public class Test {
public static void main(String[] args) {
Node head = new Node("车厢头");
Node first = new Node("车厢一");
Node second = new Node("车厢二");
Node last = new Node("车厢尾");
head.setNext(first);
first.setNext(second);
second.setNext(last);
printLink(head);
}
双链表实现:增加、删除、查询、修改、清空、设置等等功能。
//link: 负责节点之间的动态挂载
//node: 负责节点内容的设置,真实保存内容
package www.bit.java;
interface ILink{
//链表增加节点内容
boolean add(Object data);
//判断指定内容节点在链表中是否存在
int contains(Object data);
//删除指定内容节点
boolean remove(Object data);
//根据制定下标修改节点的内容
Object set(int index,Object newData);
//根据指定下标返回节点内容
Object get(int index);
//链表清空
void clear();
//将链表转为数组
Object[] toArray();
//返回链表长度
int size();
//遍历链表
void printLink();
}
//LinkImpl将Node类的动态挂载抽象出来
class LinkImpl implements ILink{
private Node head;
private Node last;
private int size;
//真正的火车车厢,负责数据存储
//内部类,外部不可见,且接口使用起来方便,无需set、get方法
private class Node{
private Node prev;
private Object data;
private Node next;
//构造方法快捷键alt+insert
public Node(Node prev, Object data, Node next) {
this.prev = prev;
this.data = data;
this.next = next;
}
}
@Override//覆写方法Ctrl+O
public boolean add(Object data) {
Node temp = this.last;
Node newNode = new Node(temp,data,null);
this.last = newNode;
if(this.head == null){
//将上一个节点的尾与当前节点的头连接
this.head = newNode;
}else{
temp.next = newNode;//将上一个节点的头连在要插入节点的头部
}
this.size++;
return true;
}
@Override
public int contains(Object data) {
if(data == null){
int i = 0;
for(Node temp = this.head; temp != null; temp = temp.next){
if(temp.data == null){
return i;
}
i++;
}
}else {
int i = 0;
for(Node temp = this.head; temp != null; temp = temp.next){
if(temp.data.equals(data) ){
return i;
}
i++;
}
}
return -1;
}
@Override
public boolean remove(Object data) {
if(data == null){
for(Node temp = this.head; temp!= null; temp = temp.next){
if(temp.data == null){
unLink(temp);
return true;
}
}
}else{
for(Node temp = this.head; temp!= null; temp = temp.next){
if(temp.data == null){
unLink(temp);
return true;
}
}
}
return false;
}
@Override
public Object set(int index, Object newData) {
if(!isLinkIndex(index)){
return null;
}
Node node = node(index);
Object elementData = node.data;
node.data = newData;
return elementData;
}
@Override
public Object get(int index) {
if(!isLinkIndex(index)){
return null;
}
return node(index).data;
}
@Override
public void clear() {
for (Node temp = head; temp!=null; ){
temp.data = null;
Node node = temp.next;
temp = temp.prev = temp.next = null;
temp = node;
this.size--;
}
}
@Override
public Object[] toArray() {
Object[] result = new Object[size];
int i = 0;
for (Node temp = head; temp != null; temp = temp.next) {
result[i++] = temp.data;
}
return result;
}
@Override
public int size() {
return this.size;
}
@Override
public void printLink() {
Object[] data = this.toArray();
for(Object temp:data){
System.out.println(temp);
}
}
//仅供本类方法使用
private Node node(int index){
if(index < (size>>1)){//小于中间节点从前往后查找
Node temp = this.head;
for(int i = 0; i<index; i++){
temp = temp.next;
}
return temp;
}
Node temp = this.last;
for(int i = size-1; i>index; i--){
temp = temp.prev;
}
return temp;
}
//判断指定索引是否合法
private boolean isLinkIndex(int index){
return index>=0 && index<size;
}
//删除节点
private Object unLink(Node x){
Object elementData = x.data;
Node prev = x.prev;
Node next = x.next;
//先判断是否为头
if(prev == null){
this.head = next;
}else{
prev.next = next;
x.prev = null;
}
//再判断是否为尾
if(next == null){
this.last = prev;
}else{
next.prev = prev;
x.next = null;
}
x.data = null;
this.size--;
return elementData;
}
}
public class Test {
public static void main(String[] args) {
ILink link = new LinkImpl();
link.add("火车头");
link.add("车厢1");
link.add("车厢2");
link.add("车厢尾");
System.out.println(link.get(3));
System.out.println(link.set(2,"bit"));
System.out.println(link.remove("车厢二"));
link.printLink();
}
}