自己写ArrayList、LinkedList、二叉差查找树、AVL树、散列(数组+列表)、非链接散列

 

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;
	}
}

 

    原文作者:AVL树
    原文地址: https://blog.csdn.net/qq_34117624/article/details/82320788
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞