1、ArrayList:
package com;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class MyArrayList<AnyType> implements Iterable<AnyType>{
private static final int DEFAULT_CAPACITY=10;
private int theSize;
private AnyType[] theItems;
public MyArrayList() {
doClear();
}
public void clear(){
doClear();
}
private void doClear() {
theSize=0;
ensureCapacity(DEFAULT_CAPACITY);
}
private void ensureCapacity(int newCapacity) {
if(newCapacity<theSize){
return;
}
if(theSize==0){
theItems=(AnyType[]) new Object[newCapacity];
return;
}
AnyType[] oldItems=theItems;
theItems=(AnyType[]) new Object[newCapacity];
for (int i = 0; i < oldItems.length; i++) {
theItems[i]=oldItems[i];
}
}
public int size(){
return theSize;
}
public boolean isEmpty(){
return theSize==0;
}
public void trimToSize(){
ensureCapacity(theSize);
}
public AnyType get(int idx){
if(idx<0 || idx>=theSize){
throw new ArrayIndexOutOfBoundsException();
}
return theItems[idx];
}
public AnyType set(int idx,AnyType newVal){
if(idx<0 || idx>theSize){
throw new ArrayIndexOutOfBoundsException();
}
AnyType oldVal = theItems[idx];
theItems[idx]=newVal;
return oldVal;
}
/**
* 虽然提供了一个在指定下标添加的方法
* 但是却无法实现跳着加,查询的时候会报一个越界的异常ArrayList也是这样定义的
* @param idx
* @param newVal
*/
public void add(int idx,AnyType newVal){
if(theItems.length==theSize){
ensureCapacity(theSize*2+1);
}
if(idx<0 || idx>theItems.length){
throw new ArrayIndexOutOfBoundsException("不要太过分");
}
/*for(int i=idx;i<theSize;i++){ 这种遍历算法上不是特别的好,最好逆序遍历
theItems[i+1]=theItems[i];
}*/
for(int i=theSize;i>idx;i--){
theItems[i]=theItems[i-1];
}
theItems[idx]=newVal;
theSize++;
}
public boolean add(AnyType newVal){
add(theSize,newVal);
return true;
}
public AnyType remove(int idx){
if(idx<0 || idx>theSize){
throw new ArrayIndexOutOfBoundsException();
}
AnyType oldVal=theItems[idx];
for(int i=idx;i<theSize-1;i++){
theItems[i]=theItems[i+1];
}
theSize--;
return oldVal;
}
@Override
public Iterator<AnyType> iterator() {
return new ArrayListIteator();
}
private class ArrayListIteator implements Iterator<AnyType>{
private int current=0;
@Override
public boolean hasNext() {
return current<theSize;
}
@Override
public AnyType next() {
if(!hasNext()){
throw new NoSuchElementException();
}
return theItems[current++];
}
/**
* 删除方法有点特殊。注意
*/
@Override
public void remove() {
MyArrayList.this.remove(--current);
}
}
}
2、LinkedList:
标记节点
头结点:开始的标记节点,其中没有存放数据
尾节点:结束的标记节点,其中没有存放数据
细节:查询方法getNode(int idx,int lower,int upper),分半查找(自己这么叫),后半部分要使用逆序遍历,因为标记节点的原因
还是这个方法,前半部分遍历的时候,for循环条件判断要加等号。否则0号位置无法获取,其他的获取也会发生错位。
内部类可以使用外部类的属性,自己写的时候不知道为什么总报错,重启了一下eclipse就好了。
package com;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class MyLinkedList<AnyType> implements Iterable<AnyType>{
private Node<AnyType> beginMarker;
private Node<AnyType> endMarker;
private int theSize;
//结构上被修改的次数
private int modCount;
public void doClear(){
beginMarker=new Node<AnyType>(null, null, null);
endMarker=new Node<AnyType>(null, beginMarker, null);
beginMarker.next=endMarker;
theSize=0;
modCount++;
}
public MyLinkedList(){
doClear();
}
public void clear(){
doClear();
}
public int size(){
return theSize;
}
public boolean isEmpty(){
return theSize==0;
}
public Node<AnyType> getNode(int idx,int lower,int upper){
Node<AnyType> p;
if(idx<lower || idx>upper){
throw new ArrayIndexOutOfBoundsException();
}
if(idx<theSize/2){
p=beginMarker;
for(int i=0;i<=idx;i++){
p=p.next;
}
}else{
p=endMarker;
for(int i=theSize;i>idx;i--){
p=p.prev;
}
}
return p;
}
public Node<AnyType> getNode(int idx){
return getNode(idx, 0, theSize);
}
public AnyType get(int idx){
Node<AnyType> node = getNode(idx);
return node.data;
}
private void addBefore(Node<AnyType> n,AnyType a){
Node<AnyType> newNode = new Node<>(a, n.prev, n);
newNode.prev.next=newNode;
n.prev=newNode;
theSize++;
modCount++;
}
public void add(AnyType a,int idx){
addBefore(getNode(idx), a);
}
public boolean add(AnyType a){
add(a, theSize);
return true;
}
public AnyType set(int idx,AnyType a){
Node<AnyType> node = getNode(idx);
AnyType oldData = node.data;
node.data=a;
return oldData;
}
private AnyType remove(Node<AnyType> n){
n.prev.next=n.next;
n.next.prev=n.prev;
theSize--;
modCount++;
return n.data;
}
public AnyType remove(int idx){
return remove(getNode(idx));
}
private static class Node<AnyType>{
public AnyType data;
public Node<AnyType> prev;
public Node<AnyType> next;
public Node(AnyType d,Node<AnyType> p,Node<AnyType> n){
data=d;
prev=p;
next=n;
}
}
@Override
public Iterator<AnyType> iterator() {
return new LinkedListIterator();
}
private class LinkedListIterator implements Iterator<AnyType>{
private Node<AnyType> current=beginMarker.next;
private int expectedModCount=modCount;
private boolean okToRemove=false;
@Override
public boolean hasNext() {
return current!=endMarker;
}
@Override
public AnyType next() {
if(expectedModCount!=modCount){
throw new ConcurrentModificationException();
}
if(!hasNext()){
throw new NoSuchElementException();
}
AnyType data = current.data;
current=current.next;
okToRemove=true;
return data;
}
@Override
public void remove() {
if(expectedModCount!=modCount){
throw new ConcurrentModificationException();
}
if(!okToRemove){
throw new IllegalStateException();
}
MyLinkedList.this.remove(current.prev);
expectedModCount++;
okToRemove=false;
}
}
}
3、二叉查找树(二叉查找树的遍历有很多中方法,自己用了一个最蠢的办法实现。。。)
package com;
public class BinarySearchTree<AnyType extends Comparable<? super AnyType>>{
private BinaryNode<AnyType> root;
public BinarySearchTree(){
root=null;
}
public void makeEmpty(){
root=null;
}
public boolean isEmpty(){
return root==null;
}
public boolean contains(AnyType a,BinaryNode<AnyType> b){
if(b==null){
return false;
}
int compareResult = a.compareTo(b.element);
if(compareResult<0){
return contains(a, b.left);
}else if(compareResult>0){
return contains(a,b.right);
}else{
return true;
}
}
public boolean contains(AnyType a){
return contains(a,root);
}
private BinaryNode<AnyType> findMin(BinaryNode<AnyType> b){
if(b==null){
return null;
}else if(b.left==null){
return b;
}
return findMin(b.left);
}
private BinaryNode<AnyType> findMax(BinaryNode<AnyType> b){
if(b!=null){
while(b.right!=null){
b=b.right;
}
}
return b;
}
public BinaryNode<AnyType> findMin(){
if(isEmpty()){
throw new ArrayIndexOutOfBoundsException();
}
return findMin(root);
}
public BinaryNode<AnyType> findMax(){
if(isEmpty()){
throw new ArrayIndexOutOfBoundsException();
}
return findMax(root);
}
private BinaryNode<AnyType> insert(AnyType a,BinaryNode<AnyType> b){
if(b==null){
return new BinaryNode<>(a, null, null);
}
int compareResult = a.compareTo(b.element);
if(compareResult<0){
b.left=insert(a, b.left);
}else if(compareResult>0){
b.right=insert(a,b.right);
}
return b;
}
public void insert(AnyType a){
root=insert(a, root);
}
private BinaryNode<AnyType> remove(AnyType a,BinaryNode<AnyType> b){
if(b==null){
return b;
}
int compareResult = a.compareTo(b.element);
if(compareResult<0){
b.left=remove(a,b.left);
}else if(compareResult>0){
b.right=remove(a,b.right);
}else if(b.left!=null && b.right!=null){
//根据二叉树排序的特点,存在两个子节点的话需要将右节点赋给要删的节点,并将有节点删除
b.element=findMin(b.right).element;
b.right=remove(b.element, b.right);
}else{
b=(b.left!=null)?b.left:b.right;
}
return b;
}
public void remove(AnyType a){
root=remove(a, root);
}
private void printTree(BinaryNode<AnyType> b){
/*if(b!=null){
System.out.println(b.element);
printTree(b.left);
printTree(b.right);
}*/
while(true){
BinaryNode<AnyType> a = findMin(b);
if(a==null){
return;
}
System.out.println(a.element);
b=remove(a.element,b);
}
}
public void printTree(){
printTree(root);
}
private static class BinaryNode<AnyType>{
private AnyType element;
private BinaryNode<AnyType> left;
private BinaryNode<AnyType> right;
public BinaryNode(AnyType e){
this(e, null, null);
}
public BinaryNode(AnyType e,BinaryNode<AnyType> l,BinaryNode<AnyType> r){
this.element=e;
this.left=l;
this.right=r;
}
}
}
4、AVL树,重要的情形的分析,再进行代码的实现。
将节点的插入分为四种情况
(1)对α节点的左儿子的左子树进行插入操作
(2)对α节点的左儿子的右子树进行插入操作
(3)对α节点的右儿子的左子树进行插入操作
(4)对α节点的右儿子的右子树进行插入操作
package com;
public class AVLTree<AnyType extends Comparable<? super AnyType>>{
private static class AvlNode<AnyType>{
private AnyType element;
private AvlNode<AnyType> left;
private AvlNode<AnyType> right;
private int hight;
public AvlNode(AnyType element){
this(element,null,null);
}
public AvlNode(AnyType a,AvlNode<AnyType> l,AvlNode<AnyType> r){
this.element=a;
this.left=l;
this.right=r;
}
}
private int hight(AvlNode<AnyType> a){
return a==null?-1:a.hight;
}
private AvlNode<AnyType> insert(AnyType a,AvlNode<AnyType> t){
if(t==null){
return new AvlNode<AnyType>(a);
}
int compareResult = a.compareTo(t.element);
if(compareResult<0){
t.left=insert(a,t.left);
}else if(compareResult>0){
t.right=insert(a,t.right);
}else{
System.out.println("插入的元素重复了!");
}
return balance(t);
}
private static final int ALLOWED_IMBALANCE=1;
private AvlNode<AnyType> balance(AvlNode<AnyType> t){
if(t==null){
return t;
}
if(hight(t.left)-hight(t.right)>ALLOWED_IMBALANCE){
if(hight(t.left.left)>=hight(t.left.right)){
t=rotateWithLeftChild(t);
}else{
t=doubleWithRightChild(t);
}
}else{
if(hight(t.right)-hight(t.left)>ALLOWED_IMBALANCE){
if(hight(t.right.right)>=hight(t.right.left)){
t=rotateWithRightChild(t);
}else{
t=doubleWithRightChild(t);
}
}
}
t.hight=Math.max(hight(t.left), hight(t.right))+1;
return t;
}
/**
* 这段代码针对的是第一种情况:在@节点的左儿子的左子树下添加一个元素的单旋
* @param k2
* @return
*/
private AvlNode<AnyType> rotateWithLeftChild(AvlNode<AnyType> k2) {
AvlNode<AnyType> k1 = k2.left;
k2.left=k1.right;
k1.right=k2;
k2.hight=Math.max(hight(k2.left), hight(k2.right))+1;
k1.hight=Math.max(hight(k1.left), k2.hight)+1;
return k1;
}
/**
* 这段代码针对的是第四种情况:在@节点的右儿子的右子树下添加一个元素的单旋
* @param k2
* @return
*/
private AvlNode<AnyType> rotateWithRightChild(AvlNode<AnyType> k2) {
AvlNode<AnyType> k1 = k2.right;
k2.right=k1.left;
k1.left=k2;
k2.hight=Math.max(hight(k2.left), hight(k2.right))+1;
k1.hight=Math.max(hight(k1.left), k2.hight)+1;
return k1;
}
/**
* 单旋其实特别好测,双旋总是报错java.lang.NullPointerException
* @param k3
* @return
*/
private AvlNode<AnyType> doubleWithRightChild(AvlNode<AnyType> k3) {
k3.left=rotateWithRightChild(k3.left);
return rotateWithLeftChild(k3);
}
public static void main(String[] args) {
AVLTree<Integer> avl=new AVLTree<>();
/*第一种插入方式的旋转测试→左左
AvlNode<Integer> a1 = avl.insert(5,null);
AvlNode<Integer> a2 = avl.insert(6,a1);
AvlNode<Integer> a3 = avl.insert(3,a2);
AvlNode<Integer> a4 = avl.insert(2,a3);
AvlNode<Integer> a5 = avl.insert(4,a4);
AvlNode<Integer> a6 = avl.insert(1,a5);*/
/*第四种插入方式的旋转测试→右右
AvlNode<Integer> a1 = avl.insert(2,null);
AvlNode<Integer> a2 = avl.insert(1,a1);
AvlNode<Integer> a3 = avl.insert(4,a2);
AvlNode<Integer> a4 = avl.insert(3,a3);
AvlNode<Integer> a5 = avl.insert(5,a4);
AvlNode<Integer> a6 = avl.insert(6,a5);*/
//第二三种情形下的测试
AvlNode<Integer> a1 = avl.insert(6,null);
AvlNode<Integer> a2 = avl.insert(7,a1);
AvlNode<Integer> a3 = avl.insert(2,a2);
AvlNode<Integer> a4 = avl.insert(1,a3);
AvlNode<Integer> a5 = avl.insert(4,a4);
AvlNode<Integer> a6 = avl.insert(3,a5);
AvlNode<Integer> a7 = avl.insert(5,a6);
System.out.println();
}
}
5、散列
package com;
import java.util.LinkedList;
import java.util.List;
public class SeparateChainingHashTable<AnyType> {
private static final int DEFAULT_TABLE_SIZE=101;
private List<AnyType>[] theLists;
private int currentSize;
public SeparateChainingHashTable(int size){
theLists=new LinkedList[nextPrime(size)];
for (int i = 0; i < theLists.length; i++) {
theLists[i]=new LinkedList<>();
}
}
public SeparateChainingHashTable(){
this(DEFAULT_TABLE_SIZE);
}
public void makeEmpty(){
for (int i = 0; i < theLists.length; i++) {
theLists[i].clear();
}
currentSize=0;
}
private int myHash(AnyType a){
int hashVal=a.hashCode();
hashVal%=theLists.length;
if(hashVal<0){
hashVal+=theLists.length;
}
return hashVal;
}
public boolean contains(AnyType a){
List<AnyType> whichList=theLists[myHash(a)];
return whichList.contains(a);
}
public void insert(AnyType a){
List<AnyType> whichList = theLists[myHash(a)];
if(!whichList.contains(a)){
whichList.add(a);
if(++currentSize>theLists.length){
rehash();
}
}
}
private void rehash() {
List<AnyType>[] oldLists = theLists;
theLists=new List[nextPrime(2*theLists.length)];
for (int i = 0; i < theLists.length; i++) {
theLists[i]=new LinkedList<>();
}
currentSize=0;
for (int i = 0; i < oldLists.length; i++) {
for(AnyType a:oldLists[i]){
insert(a);
}
}
}
public void remove(AnyType a){
List<AnyType> whichList = theLists[myHash(a)];
if(whichList.contains(a)){
whichList.remove(a);
currentSize--;
}
}
private boolean isPrime(int num){
if(num==2 || num==3){
return true;
}
if(num%6!=1 && num%6!=5){
return false;
}
for (int i = 5; i*i<=num; i+=6) {
if(num%i==0 || num%(i+2)==0){
return false;
}
}
return true;
}
private int nextPrime(int n){
boolean state = isPrime(n);
while(!state){
state=isPrime(++n);
}
return n;
}
}
6、非列表散列
package com;
public class QuadraticProbingHashTable<AnyType> {
private static final int DEFAULT_TABLE_SIZE=11;
private HashEntry<AnyType>[] array;
private int currentSize;
public QuadraticProbingHashTable(int arraySize){
allocateArray(arraySize);
makeEmpty();
}
public QuadraticProbingHashTable(){
this(DEFAULT_TABLE_SIZE);
}
private void makeEmpty() {
for (int i = 0; i < array.length; i++) {
array[i]=null;
}
currentSize=0;
}
public void insert(AnyType a){
int currentPos = findPos(a);
if(isActive(currentPos)){
return;
}
array[currentPos]=new HashEntry<>(a,true);
//书里没有currentSize前边的++,自己加的
if(++currentSize>array.length/2){
rehash();
}
}
private void rehash() {
HashEntry<AnyType>[] oldArray = array;
array=new HashEntry[nextPrime(2*array.length)];
//这里和列表散列不是一样的,没有初试化里边的HashEntry,如果初始化的话insert的时候会判断失效,包空指针异常
currentSize=0;
for (int i = 0; i < oldArray.length; i++) {
if(oldArray[i]!=null){
insert(oldArray[i].element);
}
}
}
public void remove(AnyType a){
int currentPos = findPos(a);
if(isActive(currentPos)){
array[currentPos].isActive=false;
}
}
public boolean contains(AnyType a){
int currentPos = findPos(a);
return isActive(currentPos);
}
private boolean isActive(int currentPos) {
return array[currentPos]!=null && array[currentPos].isActive;
}
/**
* 这个方法是整个类的和新方法
* @param a
* @return
*/
private int findPos(AnyType a){
int offset=1;
int currentPos=myHash(a);
while(array[currentPos]!=null && !array[currentPos].element.equals(a)){
currentPos+=offset;
offset+=2;
if(currentPos>=array.length){
currentPos-=array.length;
}
}
return currentPos;
}
private int myHash(AnyType a){
int hashVal=a.hashCode();
hashVal%=array.length;
if(hashVal<0){
hashVal+=array.length;
}
return hashVal;
}
private void allocateArray(int arraySize){
array=new HashEntry[nextPrime(arraySize)];
}
private static class HashEntry<AnyType>{
public AnyType element;
public boolean isActive;
public HashEntry(AnyType e,boolean b){
this.element=e;
this.isActive=b;
}
public HashEntry(AnyType a){
this(a, true);
}
}
private boolean isPrime(int num){
if(num==2 || num==3){
return true;
}
if(num%6!=1 && num%6!=5){
return false;
}
for (int i = 5; i*i<=num; i+=6) {
if(num%i==0 || num%(i+2)==0){
return false;
}
}
return true;
}
private int nextPrime(int n){
boolean state = isPrime(n);
while(!state){
state=isPrime(++n);
}
return n;
}
}