java由于没有指针,实现链表可以通过对象的引用代替指针记录对象位置完成
--链表的默认插入方式有两种
1.头插法:每次插入的节点为链表头,最初插入的节点为链表尾。(每个新来的数据放在最前面,类似于一个栈)
实现:需要链表类定义全局的头结点对象,每个节点包含了本身携带的数据及下个对象的引用(这里的下个对象就是在你前面进来的那个数)。
2、尾插法 :每次插入的节点放在链表尾部,符合正常人逻辑。第一个加到链表的数据为表头,后来的数据依次添加;
实现:全局变量至少得有head,最好能加last,不然每次添加元素的时候都得遍历链表全部数据才能添加下一个元素,因为你根本不能知道尾部节点在哪里,得从头一个一个找;
尾插法代码实现:
/**
* Created by 我来杀ai on 2019/4/11.
*/
public class MyLink {
/**
* * 自定义链表设计
* *
* *
* *
*
*/
Node head = null;
Node last = null;
// 头节点
/**
* * 链表中的节点,data代表节点的值,next是指向下一个节点的引用
* *
* *
* *
*
*/
class Node {
Node next = null;
// 节点的引用,指向下一个节点
int data;
// 节点的对象,即内容
public Node(int data) {
this.data = data;
}
}
/**
* * 向链表中插入数据
* *
* * @param d
*
*/
public void addNode(int d) {
Node newNode = new Node(d);
// 实例化一个节点
if (head == null) {
head = newNode;
last = newNode;
return;
}
last.next = newNode;
last = newNode;
}
/**
* *
* * @param index:删除第index个节点
* * @return
*
*/
public Boolean deleteNode(int index) {
if (index < 1 || index > length()) {
System.out.println("删除失败,没有有效节点链");
return false;
}
//头结点删除
if (index == 1) {
head = head.next;
System.out.println("删除成功,删除了头结点");
return true;
}
int flag = 2;//标识,因为设置了前驱元素,所以当前元素开始就是第2个,删头元素的情况在上面写过了
Node preNode = head; //precursor前驱 preNode前一个节点
Node curNode = preNode.next; //current当前 curNode当前节点
while (curNode != null) {
if (index == flag) {
//判断是否是删除了尾结点
if(flag == length()){
preNode.next=null;
last = preNode;
System.out.println("删除了尾结点");
return true;
}
preNode.next = curNode.next;
System.out.println("删除成功,删除了第"+flag+"个节点");
return true;
}
preNode = curNode;
curNode = curNode.next;
flag++;
}
System.out.println("删除错误");
return false;
}
/**
* *
* * @return 返回节点长度
*
*/
public int length() {
int length = 0;
Node tmp = head;
while (tmp != null) {
length++;
tmp = tmp.next;
}
return length;
}
/**
* 打印链表
*/
public void printList() {
Node tmp = head;
while (tmp != null) {
System.out.print("->|-"+tmp.data);
tmp = tmp.next;
}
System.out.println("-||");
}
/**
* 新增单链表反转功能
* @param
*/
public boolean reverse(){
if (length()<=1){
System.out.println("小于一个节点的链表不能反转");
return false;
}
Node newHead = head.next.next;//提前保存第三个节点的信息在大于2的链表使用,防止断链发生的节点丢失
last = head;//首先原本的尾部指向头部
Node second = head.next;//获得第二个节点
second.next = head;//将第二个结点的next指向第一个结点
head.next = null;//将原头结点的next指向空
head = second;//将head移到新的头结点处
//当结点数大于2时
while (newHead!=null){
Node next = newHead.next;//提前保存下个节点的信息,防止断链丢失
newHead.next = head; //将后半截链表头结点指向反转链表的头结点
head = newHead;
newHead = next;
}
return true;
}
public static void main(String[] args) {
MyLink list = new MyLink();
list.addNode(36);
list.addNode(48);
list.addNode(55);
list.addNode(56);
list.addNode(57);
list.addNode(58);
list.addNode(59);
System.out.println("linkLength:" + list.length());
System.out.println("head.data:" + list.head.data);
System.out.println("last.data:" +list.last.data);
list.printList();
list.deleteNode(7);
System.out.println("删除(7):");
list.printList();
System.out.println("打印尾结点");
System.out.println(list.last.data);
}
}
事实上单链表还是很难用,在知道一个节点的情况下,并不能直接新增或者删除节点,因为你只能知道该节点的后继,不知道他的前驱。单链表只是用来一直增加数据足够使用,如果有增删操作最好还是使用双链表,下篇博客实现双链表。
单链表不通过使用新链表反转方法 图示 (请忽略这个搓比图,关注内容就好):