自定义容器

本文详细介绍了四种基本数据结构的Java实现:栈(Stack)的基本操作如push、pop和peek,通过两个栈模拟队列(Queue)的入队和出队操作,ArrayList的动态扩容机制,以及双向链表(LinkedList)的增删查改操作。通过这些基础数据结构的理解,有助于深入掌握数据结构在实际编程中的应用。
摘要由CSDN通过智能技术生成

1.Stack

Stack 栈是一个 "先进后出"的原理

实现代码:

public class Stack {
	private int capacity=10;
	private int[]data;
	private int top=-1;
	
	public Stack() {
		data=new int[capacity];
	}
	public Stack(int capacity) {
		this.capacity=capacity;
	}
	public void push(int e) {
		top++;
		data[top]=e;
	}
	public int pop() {
		int value=data[top];
		top--;
		return value;
	}
	public int peek() {
		return data[top];
	}
	public boolean isEmpty() {
		if(top==-1)
			return true;
		return false;
	}
	public void clear() {
		data=null;
		top=-1;
	}
	public int size() {
		return top+1;
	}
	public String toString() {
		String s="";
		for(int i=top;i>=0;i--) {
			s+=data[i]+" ";
		}
		return s;
	}
}

测试操作: 

	public static void main(String[] args) {
		Stack s=new Stack();
		System.out.println(s.isEmpty());
		s.push(1);
		s.push(2);
		s.push(3);
		System.out.println(s.toString());
		System.out.println(s.peek());
		System.out.println(s.pop());
		System.out.println(s.toString());
		System.out.println(s.isEmpty());
	}

运行结果: 

true
3 2 1 
3
3
2 1 
false

2.Queue

队列 Queue :先进先出

我们需要两个栈来模仿队列:分别为入栈和出栈

当我们需要进行入栈操作时,需要判断StackB栈是否为空 若为空直接将元素加入StackA栈里,若不为空则应当将StackB栈元素加入StackA栈,再进行入栈操作。

当我们需要进行出栈操作时,需要判断StackA栈是否为空 若为空直接将元素从StackB出栈,若不为空则应当将StackA栈元素加入StackB栈,再进行出栈操作。

 实现代码

class Queue {
	private Stack stackA;
	private Stack stackB;
	public Queue() {
		stackA=new Stack();
		stackB=new Stack();
	}
	public void offer(int e) {
		stackA.push(e);
	}
	public int poll() {
		while(!stackA.isEmpty()) {
			stackB.push(stackA.pop());
		}
		return stackB.pop();
	}
	public int element() {
		while(!stackA.isEmpty()) {
			stackB.push(stackA.pop());
		}
		int temp=stackB.peek();
		while(!stackB.isEmpty()) {
			stackA.push(stackB.pop());
		}
		
		return temp;
	}
	public int size() {
		return stackA.size()+stackB.size();
	}
	public boolean isEmpty() {
		return stackA.size()==0&&stackB.size()==0;
	}
	public void clear() {
		stackA.clear();
		stackB.clear();
	}
	public String toString() {
		return stackA.toString();
	}
	public boolean equals(Object o) {
		return this.toString()==o.toString();
	}
}

测试操作:

	public static void main(String[] args) {
		Queue q=new Queue();
		System.out.println(q.size());
		System.out.println(q.isEmpty());
		q.offer(1);
		q.offer(2);
		q.offer(3);
		q.offer(4);
		System.out.println(q.element());
		System.out.println(q.size());
		q.poll();
		System.out.println(q.element());
		System.out.println(q.toString());
		System.out.println(q.isEmpty());
		q.clear();
		System.out.println(q.isEmpty());
	}

运行结果:

0
true
1
4
2
4 3 2 
false
true

3.ArrayList

我们在使用数组的时候,经常困惑的一点是怎样设置数组的大小:因为数组元素的个数可能是未知的,如果我们设置的容量太小,那么我们在添加元素的时候,不得不考虑扩容问题;如果设置的容量太大,又有可能造成空间浪费。而ArrayList的优势就在于此:我们可以在添加和去除数组元素的时候,不用去担心数组的大小设置带来的上述问题。

实现代码:

public class ArrayList {
	
	private Object[] objs;
	private int size;
	private int capacity;
	
	public ArrayList() {
		this.capacity = 10;
		this.objs = new Object[this.capacity];
	}
	
	public ArrayList(int capacity) {
		this.capacity = capacity;
		this.objs = new Object[this.capacity];
	}
	
	public void add(Object obj) {
		if (this.isFull()) {
			this.grow();
		}
		this.objs[size++] = obj;
	}

	private void grow() {
		int newCapaCity = this.capacity + (this.capacity >>> 1);
		System.out.println("扩容开始,容量由"+ this.capacity +"变为:"+ newCapaCity);
		this.objs = Arrays.copyOf(this.objs, newCapaCity);
		this.capacity = newCapaCity;
		System.out.println("扩容成功");
	}

	private boolean isFull() {
		return this.size == this.capacity;
	}
	
	public void add(int index, Object obj) {
		if (this.isFull()) {
			this.grow();
		}
		for (int i = size; i > index ; i--) {
			this.objs[i] = this.objs[i - 1];
		}
		this.objs[index] = obj;
		this.size++;
	}

	public void remove(int index) {
		for (int i = index; i < this.size; i++) {
			this.objs[i] = this.objs[i+1];
		}
		this.size--;
	}

	public boolean remove(Object obj) {
	    if (obj==null){
	        for (int i=0;i<size;i++){
	            if (objs[i]==obj){
	                remove(i);
	                return true;
	            }
	        }
	    }else {
	        for (int i=0;i<size;i++){
	            if (obj.equals(objs[i])){
	                remove(i);
	                return true;
	            }
	        }
	    }
	   return false;
	}
	
	public void update(int index, Object obj) {
		this.objs[index] = obj;
	}

	public Object load(Object Object) {
		return null;
	}

	public Object get(int index) {
		if (index < size) {
			return null;
		}
		return this.objs[index];
	}

	public Object[] list() {
		return Arrays.copyOf(this.objs, size);
	}

	public void clear() {
		this.size = 0;
	}

	@Override
	public String toString() {
		return "ArrayList [objs=" + Arrays.toString(objs) + ", size=" + size + ", capacity=" + capacity + "]";
	}
	
	public int size() {
		return this.size;
	}
	
}

测试操作:

	public static void main(String[] args) {
		ArrayList l=new ArrayList();
		System.out.println(l.isFull());
		l.add(1);
		l.add("a");
		l.add(2);
		l.add(3);
		l.add("b");
		l.add(4);
		System.out.println(l.toString());
		l.remove(1);
		l.remove(Integer.valueOf(2));
		System.out.println(l.toString());
	}

运行结果:

false
ArrayList [objs=[1, a, 2, 3, b, 4, null, null, null, null], size=6, capacity=10]
ArrayList [objs=[1, 3, b, 4, null, null, null, null, null, null], size=4, capacity=10]

4.LinkedList 

链表是一种物理存储结构上不连续的存储结构,是由存储元素的结点连接而成。每一个节点都包含前一个节点的引用,后一个节点的引用和节点存储的值。

这里实现双向链表

自定义链表的每一个节点所对应的数据结构

在这里插入图片描述

	class Node {
		Node prev;
		Node next;
		Object value;
		
		public Node() {
		}

		public Node(Node prev, Object value, Node next) {
			this.prev = prev;
			this.next = next;
			this.value = value;
		}
	}

实现代码:

public class LinkedList {
	
	private Node first;
	private Node last;
	private int size;
	
	public LinkedList() {
	}
	
	public void add(Object obj) {
		// 向尾部添加一个新的节点
		Node newNode = new Node();
		newNode.value = obj;
		// 判断是否是第一次添加
		if (first == null) {
			this.first = newNode;
			this.last = newNode;
		} else {
			newNode.prev = last;
			last.next = newNode;
			last = newNode;
		}
		this.size++;
	}
	 	//在指定位置处添加元素
    public void add(int index, Object obj) {
        if (index < 0 || index > size) {
            throw new IllegalArgumentException();
        }

        if (index == size - 1) {
            add(obj);
        } else {
            Node indexNode = getNode(index);
            Node preNode = indexNode.prev;
            Node node = new Node(preNode, obj, indexNode);
            if (preNode == null) {
                first = node;
            } else {
                preNode.next = node;
                indexNode.prev = node;
            }
            size++;
        }
    }
    //获取第index位置处的节点
    public Node getNode(int index) {
        if (index < 0 || index > size) {
            throw new IllegalArgumentException();
        }
        Node temp = first;

        for (int i = 0; i <= index; i++) {
            if (i == index) {
                return temp;
            }
            temp = temp.next;
        }

        return null;
    }
  //获取第index位置处的节点的值
	public Object get(int index) {
		if (index >= this.size || index < 0) {
			throw new RuntimeException("对不起,不存在这个下标");
		}
		Node temp = first;
		for (int i = 0; i < index; i++) {
			temp = temp.next;
		}
		return temp.value;
	}
    boolean contains(String str) {
        Node temp = first;

        for (int i = 0; i < size; i++) {
            if (temp.value.equals(str)) {
                return true;
            }
            temp = temp.next;
        }
        return false;
    }
    public String toString() {
        StringBuffer sb = new StringBuffer("[");

        Node temp = first;
        if(temp != null) {
            while (temp != null) {
                sb.append(temp.value).append(", ");
                temp = temp.next;
            }
            return sb.substring(0, sb.length() - 2)+"]";
        }
        return "";
    }
    
    public Object remove(int index) {
        if (index < 0 || index >= size) {
            throw new IllegalArgumentException();
        }

        Node node = getNode(index);
        Object res = node.value;

        Node preNode = node.prev;
        Node nextNode = node.next;

        if (preNode == null) {
            nextNode.prev = null;
            first = nextNode;
        } else if (nextNode == null) {
            preNode.next = null;
            last = preNode;
        } else {
            preNode.next = nextNode;
            nextNode.prev = preNode;
        }
        size--;

        return res;
    }
    boolean remove(Object item) {
        Node temp = first;
        for (int i = 0; i < size; i++) {
            if (temp.value.equals(item)) {
                remove(i);
            }
            temp = temp.next;
        }
        return false;
    }

    void clear() {
        Node temp = first;
        while (temp != null) {
            Node t = temp.next;
            temp.prev = null;
            temp.value = null;
            temp.next = null;
            temp = t;
        }
        first = null;
        last = null;
        size = 0;
    }
}

测试代码:

	public static void main(String[] args) {
        LinkedList linkedList = new LinkedList();
        linkedList.add("aa");
        linkedList.add("cc");
        linkedList.add("bb");
        linkedList.add("cc");
        linkedList.add("dd");
        System.out.println(linkedList);
        linkedList.remove("cc");
        System.out.println(linkedList);
        linkedList.add(2, 1);
        System.out.println(linkedList);
        linkedList.clear();
        System.out.println(linkedList.size);
	}

运行结果:

[aa, cc, bb, cc, dd]
[aa, bb, cc, dd]
[aa, bb, 1, cc, dd]
0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值