链式存储:逻辑上相邻,物理上不一定相邻,什么意思呢,比如在一堆数据中,A在B的前边,这叫逻辑相邻,而他们在计算机中的存储位置却不一定是相邻的,如果采用顺序存储,比如用一个数组来存储数据,那么逻辑相邻,物理也一定相邻,因为数组开辟的是连续的空间。因此说在采用链式存储的时候,当前的数据不仅存储数据元素,还要存储下一个元素的指针,我们把这样的数据用节点(node)来表示。如下图:
因为每一个节点都是这样的一个实例,所以我们需要创建一个NODE类,如下代码,类名为linearNode
package linkedset;
public class LinearNode<T> {
//指向下一个节点的指针
private LinearNode<T> next;
//当前节点的元素
private T element;
public LinearNode(){
next = null;
element = null;
}
//含参数的构造函数
public LinearNode(T element) {
super();
this.element = element;
}
public LinearNode<T> getNext(){
return next;
}
public T getElement() {
return element;
}
public void setElement(T element) {
this.element = element;
}
public void setNext(LinearNode<T> next) {
this.next = next;
}
}
这个类的实现是非常简单的。接下来就是实现set这个接口,set这个接口也是自己写的,因为原生的接口有很多方法我们用不上
package linkedset;
import java.util.Iterator;
public interface SetADT<T> {
/**
* 要实现的方法
*/
//添加元素
public void add(T element);
//delete element
public T remove(T element);
//add all elements
public void addAll(SetADT set);
//compare two SetADT
public boolean equals(SetADT<T> set);
//是否包含某元素
public boolean contains(T element);
//求两个SET的交集
public SetADT<T> union (SetADT<T> set);
//判断是否为空
public boolean isEmpty();
//返回set的长度
public int size();
//将SET以转为字符串
public String toString();
//返回一个迭代器
public Iterator<T> iterator();
}
现在我们写一个类来实现这个接口就可以了
package linkedset;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* @author jackee
*
* @param <T>
*/
public class LinkedSet<T> implements SetADT<T>{
private int count;
private LinearNode<T> contents;
//构造函数
public LinkedSet() {
contents = null;
count = 0;
}
@Override
public void add(T element) {
// TODO Auto-generated method stub
if(!(contains(element))){
LinearNode<T> node = new LinearNode<T>(element);
node.setNext(contents);
contents = node ;
count++;
}
}
@Override
public T remove(T element) {
LinearNode<T> previous,current;
T result;
boolean found = false;
// TODO Auto-generated method stub
//先判断首节点是不是要删除的元素
if(contents.getElement().equals(element)){
result = contents.getElement();
contents = contents.getNext();
}
//遍历整个set,找到元素为element的节点
else{
previous = contents;
current = contents.getNext();
for(int i = 1;i < count && !found;i++)
{
if(current.getElement().equals(element)){
found = true;
}else{
previous = current;
current = current.getNext();
}
}
//没找到,抛出异常
if(!found){
throw new NoSuchElementException();
}
result = current.getElement();
//将current的上一个元素的指针指向current的下一个元素
previous.setNext(current.getNext());
}
count--;
return result;
}
@Override
public void addAll(SetADT set) {
// TODO Auto-generated method stub
LinkedSet<T> set2 = (LinkedSet<T>) set;
LinkedIterator<T> li = new LinkedIterator<T>(set2.contents, set2.count);
while(li.hasNext()){
add(li.next());
}
}
@Override
public boolean equals(SetADT<T> set) {
// TODO Auto-generated method stub
boolean result = false;
LinkedSet<T> set2 = (LinkedSet<T>) set;
LinkedIterator<T> li = new LinkedIterator<T>(set2.contents, set2.count);
if(set2.size()!=this.size())
{
result = false;
}
else{
while(li.hasNext()){
if(!contains(li.next())){
break;
}else
{
result =true;
}
}
}
return result;
}
//输出set的值
public void display()
{
LinkedIterator<T> li = new LinkedIterator<T>(contents, count);
while(li.hasNext()){
System.out.print(li.next()+" ");
}
}
//是否包含某元素
@Override
public boolean contains(T element) {
// TODO Auto-generated method stub
boolean found = false;
LinkedIterator<T> li = new LinkedIterator<T>(contents, count);
while(li.hasNext())
{
if(li.next().equals(element)){
found = true ;
}
}
return found;
}
//求交集
@Override
public SetADT<T> union(SetADT<T> set) {
// TODO Auto-generated method stub
return null;
}
//判断是否为空
@Override
public boolean isEmpty() {
// TODO Auto-generated method stub
return (count == 0);
}
//set的长度
@Override
public int size() {
// TODO Auto-generated method stub
return count;
}
//返回set的迭代器
@Override
public Iterator<T> iterator() {
// TODO Auto-generated method stub
return new LinkedIterator<T>(contents,count);
}
}
在返回迭代器的时候,我们又新定义了一个类,用来生成迭代器
代码如下:
package linkedset;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class LinkedIterator<T> implements Iterator<T> {
private int count;
private LinearNode<T> current;
public LinkedIterator(LinearNode<T> collection ,int size){
current = collection;
count = size;
}
@Override
public boolean hasNext() {
// TODO Auto-generated method stub
return (current != null);
}
@Override
public T next() {
// TODO Auto-generated method stub
if(!hasNext()){
throw new NoSuchElementException();
}
T result = current.getElement();
current = current.getNext();
return result;
}
}
好,接下来就可以测试是否成功了
package linkedset;
public class LinkedSetTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
LinkedSet<Integer> test = new LinkedSet<Integer>();
test.add(14);
test.add(24);
test.add(34);
test.add(35);
test.remove(35);
test.display();
System.out.print("\n+++++++++++++++++++++++++++++\n");
test .add(34);
test.display();
System.out.println();
System.out.println(test.size());
System.out.println(test.isEmpty());
LinkedSet<Integer> test2 = new LinkedSet<Integer>();
test2.add(433);
test2.add(345);
test2.add(211);
test2.add(64);
test2.add(34);
// test.addAll(test2);
test.display();
System.out.println();
System.out.println(test.size());
LinkedSet<Integer> test3 = new LinkedSet<Integer>();
test3.add(14);
test3.add(24);
test3.add(34);
System.out.println();
System.out.println("++++++++++++++++++++++++++++++++++++++++\n");
test3.display();
System.out.println();
System.out.println(test.equals(test2));
System.out.println(test.equals(test3));
}
}
OK,方法可用,成功。