数据结构之自定义线性表 干就完了

Posted 勇敢牛牛不怕困难@帅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构之自定义线性表 干就完了相关的知识,希望对你有一定的参考价值。

数据结构与算法之线性表的实现原理及自定义线性表(基于Java基础)

在这里插入图片描述

聊一聊算法和数据结构

首先我们明白一个程序的编写过程并不是一下子就能一步完成的,例如举个例子:学生时代必不可少的学生管理系统相关的课程设计作业。采用面向对象的思想,可以把一个学生看成是一个对象,把许多学生的共同特征抽象出来成为一个类,在建立相关的方法。然而在设计中如何来存储一组学生对象呢?在查询中采用什么方法可以更快的查询到该学生呢?等等。其实在每一个步骤的设计过程中都会考虑的算法和数据结构。所以我们可以将一个程序=算法+数据结构。
什么是数据结构呢?
但凡有数据扎堆的地方,就有数据结构的影子,但凡有数据结构的地方,就脱不了算法的“折磨”。
数据结构就是将一组懒散的数据规格化,理论上来讲更便于管理。就好比现实生活中的排队购票,排队打疫苗等等,如果不排队,而是一拥而上的话,将会大大降低其速度。在排队的过程中,就可以看成是一种队列先进先出,先来的先打疫苗。
数据结构主要学习的是数据之间的关系、关系在计算机上的存储、对数据的具体操作和使用场景。
数据之间的逻辑关系-----线性结构、树形结构、图形结构
在这里插入图片描述
关系在计算机上的存储----物理结构----顺序存储结构、链式存储结构
在这里插入图片描述
什么是算法?
算法是解决特定问题求解步骤的描述,分析问题一步一步求解,并得到结果,这一系列的步骤称为算法。
在这里插入图片描述

大展身手->线性表

线性表的定义

零个或多个元素的有限序列例如下图:
在这里插入图片描述

除了第1个元素a1之外,其他元素都有唯一的直接前驱,同理除了第n个元素an之外,其他元素都有唯一的直接后继,n表示线性表的长度,当n=0时,称为空表!

自定义线性表接口

既然线性结构可以由顺序存储结构和链式结构实现,那么将两者对线性结构的共同的操作进行抽取,定义出线性结构的接口。
代码实现如下:

public interface List<E> extends Iterable<E> {

	public void add(E element);//在表的末尾增添一个元素
	public void add(int index,E element);//在指定位置添加一个元素
	public void remove(E element);//移除指定的元素
	public E remove (int index);//移除指定下标的元素并返回
	public E get(int index);//获取指定下标的元素
	public int size();//获取数组中的有效长度
	public int indexOf(E element);//查找指定元素的下标
	public boolean contains(E element);//判断元素是否在线性表中
	public boolean isEmpty();//判断线性表是否为空
	public void clear();//清空线性表
	public void sort(Comparator<E> c);//线性表进行排序
	public List<E> subList(int fromIndex,int toIndex);//截取子线性表
}

线性表的实现ArrayList

ArrayList就是线性结构顺序存储方式的具体实现,称为线性表,创建ArrayList类实现List接口,定义相关的属性和构造方法。
在这里插入图片描述

package muself_list;

import java.lang.reflect.Array;
import java.util.Comparator;
import java.util.Iterator;

public class ArrayList<E> implements List<E>{
	//存储元素的容器
	private E[] data;
	//元素的有效个数
	private int size;
	//默认容量的大小
	private static int DEFAULT_CAPACITY = 10;
     public ArrayList() {//无参构造方法,且默认长度为10
		// TODO 自动生成的构造函数存根
    	 this(DEFAULT_CAPACITY);
		
	}
     public ArrayList(int capacity) {//有参构造方法,默认长度为capacity
    	 if(capacity<0) {
    		 throw new IllegalArgumentException("initial capacity must >0");
    	 }
    	 data = (E[])new Object[capacity];
    	 size = 0;
     }
     public ArrayList(E[] arr) {//有参构造方法,默认长度为arr.length
    	 if(arr==null) {
    		 throw new IllegalArgumentException("initial arr can not null!");
    	 }
    	 data = (E[])new Object[arr.length];
    	 size = 0;
    	 for(E e:arr) {
    		 add(e);
    	 }
     }
	@Override
	public Iterator<E> iterator() {
		// TODO 自动生成的方法存根
		return null;
	}

	@Override
	public void add(E element) {
		// TODO 自动生成的方法存根
		add(size,element);
		
	}

	@Override
	public void add(int index, E element) {
		// TODO 自动生成的方法存根
		if(index<0||index>size) {
			 throw new IllegalArgumentException("add index must 0<=index<=size!");
		}
		if(size==data.length) {
			resize(data.length*2);
		}
		for(int i =size;i>index;i--) {
			data[i] = data[i-1];
		}
		data[index] = element;
		size++;
		
	}
	private void resize(int newlength) {
		E[] newData = (E[])new Object[newlength];
		for(int i=0;i<size;i++) {
			newData[i] = data[i];
		}
		data = newData;
	}

	@Override
	public void remove(E element) {
		// TODO 自动生成的方法存根
	int index = 0;
	while((index=indexOf(element))!=-1) {
		remove(index);
	}
	}

	@Override
	public E remove(int index) {
		// TODO 自动生成的方法存根
		if(index<0||index>size) {
			throw new IllegalArgumentException("add index must 0<=index<=size!");
		}
		E ret = get(index);
		for(int i = index;i<size-1;i++ ) {
			data[i] = data[i+1];
		}
		size--;
		if(size == data.length/4&&data.length>DEFAULT_CAPACITY) {
			resize(data.length/2);
		}
		return ret;
	}

	@Override
	public E get(int index) {
		// TODO 自动生成的方法存根
		if(index<0||index>size) {
			throw new IllegalArgumentException("add index must 0<=index<=size!");
		}
		return data[index];
	}

	@Override
	public E set(int index, E element) {
		// TODO 自动生成的方法存根
		if(index<0||index>size) {
			throw new IllegalArgumentException("add index must 0<=index<=size!");
		}
		E ret = data[index];
		data[index] = element;
		return ret;
	}

	@Override
	public int size() {
		// TODO 自动生成的方法存根
		return size;
	}

	@Override
	public int indexOf(E element) {
		// TODO 自动生成的方法存根
		for(int i=0;i<size;i++) {
			if(element.equals(data[i])) {
				return i;
			}
		}
		return -1;
	}

	@Override
	public boolean contains(E element) {
		// TODO 自动生成的方法存根
		
		return indexOf(element)!=-1;
	}

	@Override
	public boolean isEmpty() {
		// TODO 自动生成的方法存根
		return size==0;
	}

	@Override
	public void clear() {
		// TODO 自动生成的方法存根
		data =(E[]) new Object[DEFAULT_CAPACITY];
		size = 0;
	}

	@Override
	public void sort(Comparator<E> comparator) {
	//在这里采用的是插入排序的思想,以第一个元素作为比较对象,从下标1开始,i控制外成循环,j则去比对和i之前的数进行比较
		// TODO 自动生成的方法存根
		if(comparator==null) {
			throw new IllegalArgumentException("comparator can not null");
		}
		for(int i=1;i<size;i++) {
			E e = data[i];
			int j;
			for(j=i;j>0&&comparator.compare(data[j-1], e)>0;j--) {
				data[j] = data[j-1];
			}
			data[j] = e;
		}
		
	}
	@Override
	public List<E> sublist(int formIndex, int toIndex) {
		// TODO 自动生成的方法存根
		if(formIndex<0||formIndex>=toIndex||formIndex>=size) {
			throw new IllegalArgumentException("sublist index outof range");
		}
		ArrayList<E> list = new ArrayList<>();
		for(int i = formIndex;i<toIndex;i++) {
			list.add(data[i]);
		}
		return list;
	}
	@Override
	public String toString() {
		// TODO 自动生成的方法存根
		StringBuilder sb = new StringBuilder();
		sb.append('[');
		if(isEmpty()) {
			sb.append(']');
		}else {
			for(int i=0;i<size;i++) {
				sb.append(data[i]);
				sb.append(',');
			}
			sb.append(']');
		}
		return sb.toString();
	}
	@Override
	public boolean equals(Object obj) {
		// TODO 自动生成的方法存根
		if(obj==null) return false;
		if(obj==this) return true;
		if(obj instanceof ArrayList) {
			ArrayList<E> other = (ArrayList<E>)obj;
			if(other.size()==size) {
				for(int i=0;i<size;i++) {
					if(!this.data[i].equals(other.data[i])) {
						return false;
					}
				}
				return true;
			}else {
				return false;
			}
		}
		return false;
	}
	//返回迭代器的对象
	public Iterator<E> iterator1(){
		return new ArrayListIterator();
	}
	 private class  ArrayListIterator implements Iterator<E>{
		 private int  cur =0;
		 public boolean hasNext() {
			 return cur<size;
		 }
		 public E next() {
			 return data[cur++];
		 }
		 
	 }

}

测试代码

package muself_list;

import java.util.Comparator;
import java.util.Iterator;

public class Test {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Integer [] arr1= {3,4,5,6,7,8};
		Integer [] arr2= {3,4,5,6,7,8,11,2,3};
		ArrayList<Integer> array1 = new ArrayList<>(arr1);
		ArrayList<Integer> array2 = new ArrayList<>(arr2);
		array1.sort(new Comparator<Integer>() {
			
			@Override
			public int compare(Integer arg0, Integer arg1) {
				// TODO 自动生成的方法存根
				return arg1-arg0;
			}
		});
		Iterator<Integer> it = array1.iterator1();
		while(it.hasNext()) {
			System.out.println(it.next().toString());
		}
		System.out.println(array1.toString());
	}

}

总结

这样一个自定义的线性表就创建成功了,虽然java的API自带了List接口以及ArrayList顺序存储的线性表。其实从本质上来看,ArrayList的底层原理就是一个对象数组在进行增删改查的操作,不过只是将这个对象数组封装在内部,且隐藏于内部就是私有化,只能内部自己使用。总的来讲线性表实现原理和过程并不是特别的难,其实就是在数组基础上的修改。

以上是关于数据结构之自定义线性表 干就完了的主要内容,如果未能解决你的问题,请参考以下文章

什么返工焦虑,干就完了!

153-模型-日期表兼容农历之自定义函数 fxCalendar

软件测试周刊(第54期):管他乐观还是悲观,都滚蛋,干就完了。

jmeter之自定义java请求性能测试

Flask之自定义模型类

让Spring在你面前裸奔-扩展篇之自定义xml标签