1**除了用数组描述线性表还可以用链表描述线性表**
2在链式描述中,线性表的元素在内存中的存储位置是随机的。每个元素都有一个明确的指针或链指向线性表的下一个元素的位置(即地址)
*数组和链表的区别:
在数组中,元素的地址是由数学公式决定的,而在链式描述中,元素的地址是随机分布的
顺序表是顺序存储,非顺序存取,链表是非顺序存储。顺序存取
因此链式表便于插入,删除操作,不便于查询
3链表分为单向链表,双向链表和循环链表
首先用图片来说一下单向链表:
代码实现增删改查:
package com.tyxh.link;
//节点类
public class Node {
protected Node next; //指针域
protected int data;//数据域
public Node( int data) {
this. data = data;
}
//显示此节点
public void display() {
System. out.print( data + " ");
}
}
package com.tyxh.link;
//单链表
public class LinkList {
public Node first; // 定义一个头结点
private int pos = 0;// 节点的位置
public LinkList() {
this. first = null;
}
// 插入一个头节点
public void addFirstNode( int data) {
Node node = new Node(data);
node. next = first;
first = node;
}
// 删除一个头结点,并返回头结点
public Node deleteFirstNode() {
Node tempNode = first;
first = tempNode. next;
return tempNode;
}
// 在任意位置插入节点 在index的后面插入
public void add(int index, int data) {
Node node = new Node(data);
Node current = first;
Node previous = first;
while ( pos != index) {
previous = current;
current = current. next;
pos++;
}
node. next = current;
previous. next = node;
pos = 0;
}
// 删除任意位置的节点
public Node deleteByPos( int index) {
Node current = first;
Node previous = first;
while ( pos != index) {
pos++;
previous = current;
current = current. next;
}
if(current == first) {
first = first. next;
} else {
pos = 0;
previous. next = current. next;
}
return current;
}
// 根据节点的data删除节点(仅仅删除第一个)
public Node deleteByData( int data) {
Node current = first;
Node previous = first; //记住上一个节点
while (current. data != data) {
if (current. next == null) {
return null;
}
previous = current;
current = current. next;
}
if(current == first) {
first = first. next;
} else {
previous. next = current. next;
}
return current;
}
// 显示出所有的节点信息
public void displayAllNodes() {
Node current = first;
while (current != null) {
current.display();
current = current. next;
}
System. out.println();
}
// 根据位置查找节点信息
public Node findByPos( int index) {
Node current = first;
if ( pos != index) {
current = current. next;
pos++;
}
return current;
}
// 根据数据查找节点信息
public Node findByData( int data) {
Node current = first;
while (current. data != data) {
if (current. next == null)
return null;
current = current. next;
}
return current;
}
}
package com.tyxh.link;
//测试类
public class TestLinkList {
public static void main(String[] args) {
LinkList linkList = new LinkList();
linkList.addFirstNode(20);
linkList.addFirstNode(21);
linkList.addFirstNode(19);
//19,21,20
linkList.add(1, 22); //19,22,21,20
linkList.add(2, 23); //19,22,23,21,20
linkList.add(3, 99); //19,22,23,99,21,20
linkList.displayAllNodes();
// Node node = linkList.deleteFirstNode();
// System.out.println("node : " + node.data);
// linkList.displayAllNodes();
// node = linkList.deleteByPos(2);
// System.out.println("node : " + node.data);
// linkList.displayAllNodes();
// linkList.deleteFirstNode();
Node node = linkList.deleteByData(19);
// Node node = linkList.deleteByPos(0);
System. out.println( "node : " + node. data);
linkList.displayAllNodes();
Node node1 = linkList.findByPos(0);
System. out.println( "node1: " + node1. data);
Node node2 = linkList.findByData(22);
System. out.println( "node2: " + node2. data);
}
}
再就是双向链表:
public class DoubleLinkedList
{
// 节点类Node
private static class Node
{
Object value;
Node prev = this;
Node next = this;
Node(Object v)
{
value = v;
}
public String toString()
{
return value.toString();
}
}
private Node head = new Node(null); // 头节点
private int size; // 链表大小
// 以下是接口方法
//添加到链表表头
public boolean addFirst(Object o)
{
addAfter(new Node(o), head);
return true;
}
//将元素添加到链表表尾
public boolean addLast(Object o)
{
addBefore(new Node(o), head);
return true;
}
public boolean add(Object o)
{
return addLast(o);
}
//将元素添加到指定位置
public boolean add(int index, Object o)
{
addBefore(new Node(o), getNode(index));
return true;
}
//移除指定位置
public boolean remove(int index)
{
removeNode(getNode(index));
return true;
}
//移除链表表头元素
public boolean removeFirst()
{
removeNode(head.next);
return true;
}
//移除链表表尾元素
public boolean removeLast()
{
removeNode(head.prev);
return true;
}
//取到指定位置的元素值
public Object get(int index)
{
return getNode(index).value;
}
//返回链表的大小
public int size()
{
return size;
}
public String toString()
{
StringBuffer s = new StringBuffer("[");
Node node = head;
for (int i = 0; i < size; i++)
{
node = node.next;
if (i > 0)
s.append(", ");
s.append(node.value);
}
s.append("]");
return s.toString();
}
//以下是实现方法
//查找链表元素
private Node getNode(int index)
{
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException();
Node node = head.next;
for (int i = 0; i < index; i++)
node = node.next;
return node;
}
//在某元素之前添加元素
private void addBefore(Node newNode, Node node)
{
newNode.prev = node.prev;
newNode.next = node;
newNode.next.prev = newNode;
newNode.prev.next = newNode;
size++;
}
//在某元素之后添加元素
private void addAfter(Node newNode, Node node)
{
newNode.prev = node;
newNode.next = node.next;
newNode.next.prev = newNode;
newNode.prev.next = newNode;
size++;
}
//移除特定元素
private void removeNode(Node node)
{
node.next.prev = node.prev;
node.prev.next = node.next;
node.prev = null;
node.next = null;
size--;
}
}
//有些地方还可以优化,比如查找时可以判断索引是否大于size的一半,如果是的话,就从另一头开始迭代。
测试类
public class Test
{
public static void main(String[] args)
{
DoubleLinkedList dll = new DoubleLinkedList();
//添加
dll.add("A");
dll.add("B");
dll.add("C");
System.out.println(dll);
//添加到最前
dll.addFirst("D");
System.out.println(dll);
//添加到最后
dll.addLast("E");
System.out.println(dll);
//添加到指定位置
dll.add(4, "F");
System.out.println(dll);
//移除最前的
dll.removeFirst();
System.out.println(dll);
//移除最后的
dll.removeLast();
System.out.println(dll);
//移除指定位置上的
dll.remove(2);
System.out.println(dll);
//返回指定位置上的元素
System.out.println(dll.get(1));
}
}
1
循环链表: