链表
-
链表是一个有序的列表
-
链表是以节点的方式存储,是链式存储
-
链表的每个节点都包含data域和next域
实现单向链表的基本操作
package com.LinkedList.study;
public class LinkedListDemo {
public static void main(String[] args) {
Node n1 = new Node(1, null);
Node n2 = new Node(2, null);
Node n3 = new Node(3, null);
Node n5 = new Node(5, null);
Node n4 = new Node(4, null);
LinkedList ll = new LinkedList();
ll.add(n1);
ll.add(n2);
ll.add(n3);
ll.printList();
System.out.println("开始删除");
ll.del(3);
// ll.addByOrder(n5);
// ll.addByOrder(n4);
// ll.addByOrder(n1);
ll.printList();
}
}
/**
* 节点类
* @author 28763
*
*/
class Node {
int data;
Node next;
public Node(int data, Node next) {
super();
this.data = data;
this.next = next;
}
public Node() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Node [data=" + data + "]";
}
}
/**
* 链表类
* @author 28763
*
*/
class LinkedList {
private Node head = new Node(0, null);
private Node last = head;
/**
* 从尾部添加(普通添加,可添加重复元素,但无序)
* @param node
*/
public void add(Node node) {
last.next = node;
last = last.next;
}
/**
* 有序添加(从小到大) ,不可添加重复元素,有序
*/
public void addByOrder(Node node) {
// 如果没有节点,直接添加
if(head.next == null) {
add(node);
return;
}
// 从小到大排序
Node temp = head;
while(temp.next != null) {
// 链表中已包含该节点,添加失败
if(temp.next.data == node.data) {
System.out.println("已有节点,该次添加失败");
return;
}else if (temp.next.data > node.data) {
node.next = temp.next;
temp.next = node;
return;
}
temp = temp.next;
}
// 所添加的节点最大
add(node);
}
/**
* 打印所有节点
*/
public void printList() {
// 链表为空
if(head.next == null) {
System.out.println("链表为空!");
return;
}
Node node = head.next;
while(node != null) {
System.out.println(node);
node = node.next;
}
}
/**
* 删除数据
* @param data
*/
public void del(int data) {
if(head.next == null) {
System.out.println("链表为空,无数据可删除");
return;
}
Node node = head;
while(node.next != null) {
if(node.next.data == data) {
node.next = node.next.next;
return;
}
node = node.next;
}
System.out.println("未找到该数据");
}
}
相关扩展
-
求链表中有效的节点
/** * 得到有效的节点树 */ public int getEffectiveNode(Node head) { if(head == null || head.next == null) { return 0; } int num = 0; Node node = head.next; while(node != null) { num++; node = node.next; } return num; }
-
查找单链表倒数第k个节点(新浪)
包含两种方式:
- 通过两次遍历,第一次遍历获取链表节点总数total,将total - k就是下一次遍历的步数,最终第二次遍历停止的地方为倒数第k个节点。
- 通过双指针同时进行遍历(仅遍历1遍),当第一个指针遍历k步时,第二个指针开始遍历(此时是第一个指针和第二个指针同时遍历),当第一个指针指向链表结尾时,第二个指针指向的几点便是倒数第k个节点。代码如下(采用第二种方式):
/** * 查找倒数第k个节点 */ public Node getCountdownNode(Integer k) { if(head == null || head.next == null) { return null; } int num = 0; Node n1 = head; Node n2 = head; while(n1.next != null) { n1 = n1.next; num++; if(num >= k) { n2 = n2.next; } } return n2; }
-
单链表的反转(腾讯)
/** * 反转链表 */ public void reverseLinkedNode() { if(head == null || head.next == null) { return; } Node first = new Node(0, null); Node n1 = head.next; Node n2 = n1; n1 = n1.next; n2.next = null; first.next = n2; while(n1 != null) { n2 = n1; n1 = n1.next; n2.next = first.next; first.next = n2; } head.next = first.next; }
-
从尾到头打印单链表【反向遍历、使用栈】(百度)
-
使用栈的方式实现:
/** * 倒序打印 */ public void reversePrint() { Stack<Integer> stack = new Stack<Integer>(); Node node = head.next; while(node != null) { stack.add(node.data); node = node.next; } while(!stack.isEmpty()) { System.out.printf("序号:%d, 值:%d\n", stack.indexOf(stack.lastElement()), stack.pop()); } }
-