1.简易版LinkedList的实现
package com.upupgogogo;
/**
* Created by upupgogogo on 2018/3/20.下午1:19
*/
public class Node<T> {
public T data;
public Node<T> next;
public Node(T date, Node<T> next){
this.data = date;
this.next = next;
}
public Node(){
this(null,null);
}
}
通过节点的形式保存数据以及下个数据的
package com.upupgogogo;
/**
* Created by upupgogogo on 2018/3/20.下午1:23
*/
public class SinglyLinkedList<T> implements LList<T> {
private Node<T> head;
private int size;
//初始化节点和保存数据的大小
public SinglyLinkedList() {
this.head = new Node<T>();
this.size = 0;
}
public boolean isEmpty() {
return this.size == 0;
}
public int length() {
return this.size;
}
public void add(int index, T x) {
//1.判参数
if (index < 0 || index > size)
throw new IndexOutOfBoundsException("Index: " +index+ "," +"Size: "+this.size);
//2.找节点(插入点的前一个节点)
Node<T> p = this.head;
for (int j = 0; j < index; j++)
p = p.next;
//3.插入节点
p.next = new Node<T>(x,p.next);
//size加一
this.size++;
}
public void add(T x) {
add(this.size,x);
}
public T remove(int index) {
//判断index是否有效
checkElement(index);
//得到头结点
Node<T> p = this.head;
//找到index节点的前一个节点
for (int j = 0; j < index; j++)
p = p.next;
//得到保存的数据
T x =(T)p.next.data;
//让该节点的前节点的next指针指向该节点的下个节点
p.next = p.next.next;
//数据长度减一
this.size--;
return x;
}
public void set(int index, T x) {
checkElement(index);
Node<T> p = this.head;
for (int j = 0; j < index; j++)
p = p.next;
p.next.data = x;
}
public T get(int index) {
checkElement(index);
Node<T> p = this.head;
for (int j = 0; j < index; j++)
p = p.next;
return p.next.data;
}
private void checkElement(int index){
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException("Index: " +index+ "," +"Size: "+this.size);
}
public int contain(T x){
Node<T> p = head.next;
int i = -1;
while (p != null){
i++;
if (p.data .equals(x)){
p.data = x;
return i;
}
p = p.next;
}
return -1;
}
public String toString() {
String str = "";
Node<T> p = head;
for (int j = 0; j < size; j++){
p = p.next;
str = str + p.data.toString() +",";
}
if (str.length() > 0)
str = str.substring(0,str.length()-1);
return "["+str+"]";
}
public static void main(String[] args) {
LList lList = new SinglyLinkedList();
lList.add(19);
lList.add(20);
lList.remove(0);
System.out.println(lList);
}
}
得到输出结果:
[20]
2.基于单链表数组来实现hash表
package com.upupgogogo;
import java.util.HashSet;
/**
* Created by upupgogogo on 2018/3/21.上午10:30
*/
public class NoBaseMapHashSet<T> {
private SinglyLinkedList<T>[] table; //单链表数组来保存数据
private static final int DEFAULT_VALUE = 16;
private int size; //容器所装载的数据大小
private static final float LOAD_FACTOR = 0.75f; //加载因子
private int ciritical_vale; //容器所装载的临界值
public NoBaseMapHashSet(){
//初始化数组
this.table = new SinglyLinkedList[DEFAULT_VALUE];
//初始化数组的每个单链表对象
initSinglyLinkedList(table.length);
this.size = 0;
//初始容器所装载的临界值
this.ciritical_vale = (int)(LOAD_FACTOR*DEFAULT_VALUE);
}
private void initSinglyLinkedList(int value){
for (int i = 0; i < value; i++){
table[i] = new SinglyLinkedList<T>();
}
}
private int index(T key) {
//根据key的hashcode和table长度取模计算key在table中的位置
if (key == null)
throw new NullPointerException("NO NULL");
return key.hashCode() % table.length;
}
public void add(T key){
//判断是否包含保存的数据
if (contain(key) != -1)
return;
//判断是否需要扩容
resize();
//先通过hash值判断单链表所属数组位置,然后调用单链表的add方法添加数据
table[index(key)].add(key);
//数据长度加一
size++;
}
//扩容
private void resize(){
//判断数据大小是否已达临界值
if (this.size >= this.ciritical_vale){
//申明一个临时变量保存原有的数据
SinglyLinkedList[] temp = this.table;
//初始化一个两倍长度的单链表数组
this.table = new SinglyLinkedList[table.length*2];
initSinglyLinkedList(table.length);
for (int j =0; j < temp.length; j++)
table[j] = temp[j];
//重新初始化临界值
ciritical_vale = (int) (table.length * LOAD_FACTOR);
}
}
public void remove(T key){
//判断是否包含此数据
if (contain(key) != -1)
return;
//通过得到此数据所处单链表的index值,然后调用单链表的remove删除数据
table[index(key)].remove(contain(key));
size--;
}
public String toString() {
String str = "";
for (int j = 0; j < table.length; j++){
if (table[j] != null){
for (int i = 0; i < table[j].length(); i++)
str = str + table[j].get(i).toString() + ",";
}
}
if (str.length() > 0)
str = str.substring(0,str.length()-1);
return "["+str+"]";
}
public int contain(T key){
//1.通过hashcode方法得到所属单链表下标
//2.通过equals方法判断是否相同
//3.返回该数据所处单链表的位置,若不存在则返回-1
return table[index(key)].contain(key);
}
public static void main(String[] args) {
NoBaseMapHashSet hashSet = new NoBaseMapHashSet();
hashSet.add(19);
hashSet.add(18);
hashSet.add(19);
System.out.println(hashSet);
}
}
输出结果
[18,19]
处理单链表的关键之处就是在于处理他的头结点,通过头结点得到每个节点从而进行增删改查,以及扩容
而操作hash表的关键就在于通过hashcode来确定单链表,通过equals来确定是否进行添加或者覆盖删除,以及扩容