数据结构-线性表

线性表

零个或多个数据元素的有限序列

  • 在较复杂的线性表中,一个数据元素可以由若干个数据项组成

线性表的抽象数据类型

除了第一个元素外,每一个元素有且只有一个直接前驱元素,除了最后一个元素外,每个元素有且只有一个直接后继元素,数据元素之间是一对一关系

线性表的顺序存储结构

线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素

静态数组与动态数组

  • Java中内置的数组的特点:
    1、数组的长度一旦确定则不可更改
    2、数组只能存储同一类型的数据
    3、数组中每个存储空间地址是连续且相等的
    4、数组提供角标的方式访问元素
  • 静态数组缺点:
    1、长度不可变,数据量大了怎么办?扩容可以解决(创建新数组)
    2、地址连续且提供角标,访问很快,但移动元素只能挨个挨个移
    3、最重要的,数组只有length这个属性,没有其他的方法
  • 何为动态数组呢,主要是解决其缺点3
    1、将数组本身和在其上的相关操作进行封装,生成一个类
    2、今后只需创建该类的对象,就可以进行对其所包装的数组进行增删改查操作

动态数组——线性表的顺序存储结构

List 线性表接口定义
package dyarray;
public interface MyList<E> {
	public int getSize();//获取元素个数
	public boolean isEmpty();//判断是否为空
	public void add(int index,E e);//在指定index处添加元素e
	public void addFirst(E e);//在列表第一个位置添加元素
	public void addLast(E e);//在列表中最后一个位置添加元素
	public E get(int index);//获取index处的元素
	public E getFirst();//获取列表中第一个元素
	public E getLast();//获取列表中最后一个元素
	public E remove(int index);//删除指定位置的值
	public E removeFirst();//删除第一个元素
	public E removeLast();//删除最后一个元素
	public void set(int index,E e);//修改列表中指定角标元素为e
	public boolean contains(E e);//判断是否包含e
	public int find(E e);//在列表中查找e的角标
	public void removeElement(E e);//在列表中删除指定元素e
	public void clear();//清空列表
	public int getCapacity();//获取最大容量
	public String toString();
}

ArrayList顺序表实现
package dyarray;

public class MyArrayList<E> implements MyList<E>{
	private E[] arr;
	private int size;//当前列表中的个数
	private static final int DEFAULT_CAPACITY=10;
	public MyArrayList(){
		this(DEFAULT_CAPACITY);
	}
	public MyArrayList(int capacity){
		if(capacity<0){
			System.out.println("传参错误,默认10");
			capacity=DEFAULT_CAPACITY;
		}
		arr=(E[])new Object[capacity];
		this.size=0;
	}
	@Override
	public int getSize() {
		// TODO Auto-generated method stub
		return size;
	}

	@Override
	public boolean isEmpty() {
		// TODO Auto-generated method stub
		
		return size==0?true:false;
	}

	@Override
	public void add(int index, E e) {
		// TODO Auto-generated method stub
		if(index<0||index>size){
			throw new IllegalArgumentException("角标非法!");
		}
		if(size==arr.length){
			//扩容
			System.out.println("shi");
			resize();//重置容量
		}
		for(int i=size-1;i>=index;i--){
			arr[i+1]=arr[i];
		}
		arr[index]=e;
		size++;
	}

	@Override
	public void addFirst(E e) {
		// TODO Auto-generated method stub
		add(0,e);
	}

	@Override
	public void addLast(E e) {
		// TODO Auto-generated method stub
		add(size,e);
	}

	@Override
	public E get(int index) {
		// TODO Auto-generated method stub
		if(index<0||index>=arr.length){
			throw new IllegalArgumentException("角标越界");
		}
		return arr[index];
	}

	@Override
	public E getFirst() {
		// TODO Auto-generated method stub
		return get(0);
	}

	@Override
	public E getLast() {
		// TODO Auto-generated method stub
		return get(size-1);
	}

	@Override
	public E remove(int index) {
		// TODO Auto-generated method stub
		if(index<0||index>=size){
			throw new IllegalArgumentException("角标非法!");
		}
		E temp=arr[index];
		for(int i=index;i<size-1;i++){
			arr[i]=arr[i+1];
		}
		size--;
		resize();
		return temp;
	}

	@Override
	public E removeFirst() {
		// TODO Auto-generated method stub
		E temp=arr[0];
		remove(0);
		return temp;
	}

	@Override
	public E removeLast() {
		// TODO Auto-generated method stub
		E t=arr[size-1];
		remove(size-1);
		return t;
	}

	@Override
	public void set(int index, E e) {
		// TODO Auto-generated method stub
		if(index<0||index>=arr.length){
			throw new IllegalArgumentException("角标越界");
		}
		arr[index]=e;
	}

	@Override
	public boolean contains(E e) {
		// TODO Auto-generated method stub
		
		return (find(e)==-1)?false:true;
	}

	@Override
	public int find(E e) {
		// TODO Auto-generated method stub
		for(int i=0;i<size;i++){
			if(arr[i]==e){
				return i;
			}
		}
		return -1;
	}

	@Override
	public void removeElement(E e) {
		// TODO Auto-generated method stub
		for(int i=0;i<size;i++){
			if(arr[i]==e){
				remove(i);
			}
		}
	}

	@Override
	public void clear() {
		// TODO Auto-generated method stub
		arr=(E[])new Object[DEFAULT_CAPACITY];
		size=0;
	}
	
	private void resize() {
		// TODO Auto-generated method stub
		
		if(size==arr.length){
			E[] newArr=(E[])new Object[getCapacity()*2];
			for (int i=0;i<size;i++) {
				newArr[i]=arr[i];
			}
			arr=newArr;
		}else if(size<=arr.length/4&&arr.length>DEFAULT_CAPACITY){
			E[] newArr=(E[])new Object[getCapacity()/2];
			for(int i=0;i<newArr.length;i++){
				newArr[i]=arr[i];
			}
			arr=newArr;
		}
	}
	@Override
	public int getCapacity() {
		// TODO Auto-generated method stub
		return arr.length;
	}
	public void swap(int i,int j){
		if(i<0||i>=size||j<0||j>=size){
			throw new IllegalArgumentException();
		}
		E temp=arr[i];
		arr[i]=arr[j];
		arr[j]=temp;
	}
	public String toString(){
		StringBuilder sb=new StringBuilder();
		if(isEmpty()){
			sb.append(String.format("ArrayList:[] %d/%d \n",size,arr.length));
		}else{
			sb.append(String.format("ArrayList:["));
			for(int i=0;i<size;i++){
				if(i==size-1){
					sb.append(arr[i]);
				}else{
					sb.append(arr[i]+",");
				}
			}
			sb.append(String.format("] %d/%d \n", size,arr.length));
		}
		return sb.toString();
		
	}

}

动态数组——栈的顺序存储结构

Stack的接口定义
package dyarray;

public interface MyStack<E> {
	public void push(E e);//进栈
	public E pop();//出栈
	public boolean isEmpty();//判断栈是否为空
	public E peek();//获取当前栈顶元素,不去除
	public int getSize();//栈内元素的数量
	public void clear();//清空栈
}

ArrayStack 顺序栈类实现
package dyarray;

public class MyArrayStack<E> implements MyStack<E>{
	private MyArrayList<E> list;
	public MyArrayStack(){
		this(10);
	}
	public MyArrayStack(int capacity){
		list=new MyArrayList<>(capacity);
	}
	@Override
	public void push(E e) {
		// TODO Auto-generated method stub
		list.addLast(e);
	}

	@Override
	public E pop() {
		// TODO Auto-generated method stub
		return list.removeLast();
	}

	@Override
	public boolean isEmpty() {
		// TODO Auto-generated method stub
		return list.isEmpty();
	}

	@Override
	public E peek() {
		// TODO Auto-generated method stub
		return list.getLast();
	}

	@Override
	public int getSize() {
		// TODO Auto-generated method stub
		return list.getSize();
	}

	@Override
	public void clear() {
		// TODO Auto-generated method stub
		list=new MyArrayList<>();
	}
	@Override
	public String toString() {
		StringBuilder sb=new StringBuilder();
		if(isEmpty()){
			sb.append(String.format("ArrayStack:bottom[]top %d/%d",getSize(),getCapacity()));
		}else{
			sb.append("ArrayStack:bottom[");
			for(int i=0;i<list.getSize();i++){
				if(i==list.getSize()-1){
					sb.append(list.get(i)+"]");
				}else{
					sb.append(list.get(i)+",");
				}
			}
			sb.append(String.format("top %d/%d \n",getSize(),getCapacity()));
		}
		return sb.toString();
	}
	private int getCapacity() {
		// TODO Auto-generated method stub
		return list.getCapacity();
	}

}

动态数组——双端栈的顺序存储结构

双端栈:是指从一个线性表的两端当做栈底进行分别的入栈和出栈操作

ArrayStackDoubleEnd 顺序双端栈类实现
package dyarray;

public class ArrayStackDoubleEnd<E> implements MyStack<E>{
	private E[] data;
	private static final int DEFAULT_CAPACITY=10;
	public static final int L=0;
	public static final int R=1;
	private int right;
	private int left;
	private int size;
	
	public ArrayStackDoubleEnd() {
		this(DEFAULT_CAPACITY);
	}
	public ArrayStackDoubleEnd(int capacity){
		data=(E[])new Object[capacity];
		left=-1;
		right=data.length;
		size=0;
	}
	public void push(int which,E e){
		if(size==data.length){
			//扩容
			resize();
		}
		if(which==L){
			data[++left]=e;
		}else{
			data[--right]=e;
		}
		size++;
	}
	
	private void resize() {
		// TODO Auto-generated method stub
		if(size==data.length){
			E[] newArr=(E[])new Object[getCapacity()*2];
			for (int i=0;i<=left;i++) {
				newArr[i]=data[i];
			}
			for(int i=data.length;i>=right;i--){
				newArr[i]=data[i];
			}
			data=newArr;
		}else if(size<=data.length/4&&data.length>DEFAULT_CAPACITY){
			E[] newArr=(E[])new Object[getCapacity()/2];
			for (int i=0;i<=left;i++) {
				newArr[i]=data[i];
			}
			for(int i=data.length;i>=right;i--){
				newArr[i]=data[i];
			}
			data=newArr;
		}
	}
	public int getCapacity(){
		return data.length;
	}
	public int getSize(int which){
		if(which==L){
			return left+1;
		}else{
			return data.length-right;
		}
	}
	public E peek(int which){
		if(isEmpty(which)){
			throw new IllegalArgumentException("栈以空");
		}
		if(which==L){
			return data[left];
		}else{
			return data[right];
		}
	}
	public E pop(int which){
		if(isEmpty(which)){
			throw new IllegalArgumentException("栈以空");
		}
		size--;
		if(which==L){
			return data[left--];
		}else{
			return data[right++];
		}
		
	}
	private boolean isEmpty(int which) {
		// TODO Auto-generated method stub
		if(which==L){
			return left==-1?true:false;
		}else{
			return (right==data.length)?true:false;
		}
	}
	public void clear(int which){
		if(which==L){
			size-=(left+1);
			left=-1;
		}else{
			size-=(data.length-right);
			right=data.length;
		}
	}
	public String toString(){
		StringBuilder sb=new StringBuilder();
		if(isEmpty()){
			sb.append(String.format("ArrayStackDoubleEnd:bottom[]top[]bottom %d/%d",size,data.length));
		}else{
			sb.append("ArrayStackDoubleEnd:bottom[");
			for(int i=0;i<=left;i++){
				if(i==left){
					sb.append(data[i]+"]top[");
				}else{
					sb.append(data[i]+",");
				}
			}
			
			for(int i=right;i<data.length;i++){
				if(i==data.length-1){
					sb.append(data[i]);
				}else{
					sb.append(data[i]+",");
				}
				
			}
			sb.append(String.format("]bottom %d/%d",size,data.length));
		}
		return sb.toString();
	}
	@Override
	public void push(E e) {
		// TODO Auto-generated method stub
		if(getSize(0)>getSize(1)){
			push(1,e);
		}else{
			push(0,e);
		}
	}
	@Override
	public E pop() {
		// TODO Auto-generated method stub
		E temp=null;
		if(getSize(0)>getSize(1)){
			temp=pop(0);
		}else{
			temp=pop(1);
		}
		return temp;
	}
	
	@Override
	public boolean isEmpty() {
		// TODO Auto-generated method stub
		return isEmpty(0)&&isEmpty(1)?true:false;
	}

	@Override
	public E peek() {
		// TODO Auto-generated method stub
		E temp=null;
		if(getSize(0)>getSize(1)){
			temp=peek(0);
		}else{
			temp=peek(1);
		}
		return temp;
	}

	@Override
	public int getSize() {
		// TODO Auto-generated method stub
		return size;
	}

	@Override
	public void clear() {
		// TODO Auto-generated method stub
		data=(E[])new Object[DEFAULT_CAPACITY];
	}

}

动态数组——队列的顺序存储结构

Queue 队列接口定义
package dyarray;

public interface MyQueue<E> {
	public int getSize();//获取队列中元素的个数
	public boolean isEmpty();
	public void enqueue(E e);//入队
	public E dequeue();//出队
	public E getFront();//获得队头元素
	public E getRear();//获得队尾元素
	public void clear();//清空队列
}

ArrayQueue 顺序队列类实现
package dyarray;

public class ArrayQueue<E> implements MyQueue<E>{
	private MyList<E> list;
	public ArrayQueue() {
		this(10);
	}
	public ArrayQueue(int capacity) {
		list=new MyArrayList<>(capacity);
	}
	@Override
	public int getSize() {
		// TODO Auto-generated method stub
		return list.getSize();
	}

	@Override
	public boolean isEmpty() {
		// TODO Auto-generated method stub
		return list.isEmpty();
	}

	@Override
	public void enqueue(E e) {
		// TODO Auto-generated method stub
		list.addLast(e);
	}

	@Override
	public E dequeue() {
		// TODO Auto-generated method stub
		return list.removeFirst();
	}

	@Override
	public E getFront() {
		// TODO Auto-generated method stub
		return list.getFirst();
	}

	@Override
	public E getRear() {
		// TODO Auto-generated method stub
		return list.getLast();
	}

	@Override
	public void clear() {
		// TODO Auto-generated method stub
		list=new MyArrayList<>();
	}

}

动态数组——循环队列的顺序存储结构

ArrayQueueLoop 循环顺序队列类实现
package dyarray;

public class ArrayQueueLoop<E> implements MyQueue<E>{
	private E[] data=null;
	private static final int DEFAULT_CAPACITY=10;
	private int front;
	private int rear;
	private int size;
	public ArrayQueueLoop() {
		this(DEFAULT_CAPACITY);
	}
	public ArrayQueueLoop(int capacity){
		data=(E[])new Object[capacity+1];
		rear=0;
		front=0;
		size=0;
	}

	@Override
	public int getSize() {
		// TODO Auto-generated method stub
		return size;
	}

	@Override
	public boolean isEmpty() {
		// TODO Auto-generated method stub
		return rear==front?true:false;
	}

	@Override
	public void enqueue(E e) {
		// TODO Auto-generated method stub
		if(size==data.length-1){
			resize();
		}
		if(rear==data.length-1){
			data[rear]=e;
			size++;
			rear=(rear+1)%data.length;
		}else{
			size++;
			data[rear++]=e;
		}
		
		
	}
	public int getCapacity(){
		return data.length;
		
	}
	public void resize(){
			E[] newArr=(E[])new Object[getCapacity()*2];
			int index=0;
			for(int i=front;i!=rear;i=(i+1)%data.length){
				newArr[index++]=data[i];
			}
			data=newArr;
	}
	@Override
	public E dequeue() {
		// TODO Auto-generated method stub
		E temp=null;
		if(front==data.length-1){
			temp=data[front];
			size--;
			front=(front+1)%data.length;
		}else{
			size--;
			temp=data[front++];
		}
		return temp;
	}

	@Override
	public E getFront() {
		// TODO Auto-generated method stub
		return data[front];
	}

	@Override
	public E getRear() {
		// TODO Auto-generated method stub
		return data[rear-1];
	}

	@Override
	public void clear() {
		// TODO Auto-generated method stub
		data=(E[])new Object[DEFAULT_CAPACITY];
		size=0;
		rear=0;
		front=0;
	}
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		StringBuilder sb=new StringBuilder();
		if(isEmpty()){
			sb.append(String.format("ArrayQueueLoop:[] %d/%d",size,data.length));
		}else{
			sb.append("ArrayQueueLoop:[");
			for(int i=front;i!=rear;i=(i+1)%data.length){
				if((i+1)%data.length==rear){
					sb.append(data[i]+"]");
				}else{
					sb.append(data[i]+",");
				}
			}
			sb.append(String.format(" %d/%d",size,data.length));
		}
		
		return sb.toString();
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值