一、链接存储
集合的顺序存储是通过数组实现的,而集合的链接存储是通过存储结点之间的链接实现的,链接形成的结果是一个链接表。构成链接表的每个结点由值域和指针域构成,值域存储数据,指针域是下一个结点的引用,以此来指向下一个结点。这样一个结点链接另一个结点构成的是一个单链表。第一结点称作表头结点,最后一个结点称作表尾结点。前面的结点称作前驱结点,指针指向的结点称作后继结点。
二、链表实现集合
- Node
package set;
/**
* 链表存储的结点由值域和指针域组成
*/
public class Node {
//值域
Object element;
//指针域
Node next;
public Node(Node next) {
this.next = next;
}
public Node(Object element, Node next) {
this.element = element;
this.next = next;
}
}
- LinkedSet
首先有一个表头指针,用head表示,是一个Node类型的数据,其值是附加表头结点的引用。head.next表示是链表的第一个元素的引用。有一个长度用length表示,初始化的LinkedSet的length为0,说明附加表头是不占元素数量的。
package set;
public class LinkedSet implements Set {
//表头指针
private Node head;
//长度
private int length;
public LinkedSet() {
length = 0;
//表头指针指向附加头结点,附加头结点的指针域为null表示为空链表
head = new Node(null);
}
/**
* 1.操作表头指针遍历链表,如果链表中有相同的数据则返回false
* 2.如果链表中没有,此时表头指针已经是表尾结点了。
* 3.在链表的尾部插入元素
*
* @param obj
* @return
*/
@Override
public boolean add(Object obj) {
Node p = head;
//遍历链表,把p不断往后移动,直到最后一个元素,操作的是表头指针
while (p.next != null) {
if (obj.equals(p.next.element)) return false;
//把p从head变为附加头结点
p = p.next;
}
//如果p.next=null表明是表尾结点,在链表的结尾插入元素
p.next = new Node(obj, null);
length++;
return true;
}
@Override
public boolean remove(Object obj) {
Node p = head;
while (p.next != null) {
//如果有元素有Obj相同,跳出循环
if (obj.equals(p.next.element)) break;
p = p.next;
}
//p是附加头结点,p.next是要删掉的元素
if (p.next != null) {
p.next = p.next.next;
length--;
return true;
}
return false;
}
@Override
public boolean contains(Object obj) {
Node p = head;
while (p.next != null) {
if (obj.equals(p.next.element)) return true;
p = p.next;
}
return false;
}
@Override
public Object value(int index) {
if (index > length - 1 || index < 0) {
throw new IllegalArgumentException("Wrong arg, please input a correct arg");
}
Node p = head;
int counter = 0;
while (p.next != null) {
if (index == counter) return p.next.element;
counter++;
p = p.next;
}
return null;
}
@Override
public Object find(Object obj) {
Node p = head;
while (p.next != null) {
if (obj.equals(p.next.element)) return p.next.element;
p = p.next;
}
return null;
}
@Override
public int size() {
return length;
}
@Override
public boolean isEmpty() {
return length == 0;
}
@Override
public void outputAll() {
Node p = head;
while (p.next != null) {
System.out.println(p.next.element);
p = p.next;
}
}
@Override
public Set union(Set set) {
LinkedSet destSet = new LinkedSet();
LinkedSet linkedSet = (LinkedSet) set;
Node p = head;
while (p.next != null) {
destSet.add(p.next.element);
p = p.next;
}
Node q = linkedSet.head;
while (q.next != null) {
destSet.add(q.next.element);
q = q.next;
}
return destSet;
}
@Override
public Set intersection(Set set) {
LinkedSet tempSet = new LinkedSet();
LinkedSet linkedSet = (LinkedSet) set;
Node p = head;
while (p.next != null) {
if (linkedSet.contains(p.next.element)) tempSet.add(p.next.element);
p = p.next;
}
return tempSet;
}
@Override
public void clear() {
length = 0;
head.next = null;
}
@Override
public String toString() {
int iMax = length - 1;
if (iMax == -1) return "[]";
StringBuilder sb = new StringBuilder();
sb.append("[");
Node p = head;
for (int i = 0; ; i++) {
sb.append(String.valueOf(p.next.element));
//如果是最后一个的话
if (i == iMax) return sb.append("]").toString();
sb.append(", ");
p = p.next;
}
}
}
- 测试类
package setTest;
import set.LinkedSet;
public class LinkedSetTest {
public static void main(String[] args) {
LinkedSet linkedSet = new LinkedSet();
linkedSet.add("ok");
linkedSet.add("hello");
linkedSet.add("world");
System.out.println(linkedSet);
linkedSet.remove("ok");
System.out.println(linkedSet);
System.out.println(linkedSet.contains("ok"));
System.out.println(linkedSet.value(1));
System.out.println(linkedSet.find("hello"));
System.out.println("=====================");
System.out.println(linkedSet);
LinkedSet uSet = new LinkedSet();
uSet.add("a");
uSet.add("b");
uSet.add("hello");
System.out.println(linkedSet.union(uSet));
System.out.println(linkedSet);
System.out.println(uSet);
System.out.println(linkedSet.intersection(uSet));
}
}