数据结构(Java 实现)之线性表

最近从图书馆借了一本数据结构(Java 语言描述)的书,作者是丁海军老师。上过 C 语言版实现的课程,觉得两者思路大致一样,只是在表达方式有所不同,学完第一章线性表之后,决定写一篇博客为自己总结一下学习情况。

线性表(list)是一种线性结构。线性结构的特点是具有相同数据类型的 n (n >= 0) 个数据元素的有限序列,它们一个接着一个排列,第一个元素没有直接前驱,最后一个元素没有直接后继,中间的元素有一个直接前驱和一个直接后继。当线性表的长度为 0 时,成为空表,表示一个元素都没有。

数据结构的三要素,即数据的逻辑结构、数据的存储结构、数据操作。

数据的逻辑结构是对数据结构的数学抽象,它独立于计算机,是数据元素与数据元素之间存在的一种关系。数据的存储结构也叫物理存储结构,它是数据结构在计算机的实现。主要分为顺序存储结构和链式存储结构,线性表也从这两个结构来实现。数据操作,也就是我们可以在这个数据结构上进行的操作。如最基本的增、删、改、查。

下面我们使用 Java 先实现线性表的顺序存储结构,也叫顺序表。而链式存储结构实现的我们可以称为链表。既然线性表是抽象的,那么就我们可以抽象出来一些顺序表和链表共同的部分,这部分独立于计算机的实现,我们把它定义为一个抽象类 AbsList。下面是这个类的代码部分。

package oldbiwang.ds;
import java.util.Iterator;
public abstract class AbsList<T> implements Iterable<T> {
		//长度
		protected int length;
		//返回第 i (i >= 0)个元素
		abstract public T get(int i);
		//设置第 i 个元素为 x
		abstract public boolean set(int i, T x);
		//查找,返回首次出现的关键字为 key 的元素
		abstract public int indexOf(int begin, int end, T o);
		//插入 x 作为第 i 个元素
		abstract public void add(int i, T x);
		//删除第 i 个位置的数据元素并返回删除对象
		abstract public void remove(int i)
		//返回一个迭代器
		abstract public Iterator<T> iterator();
		//判断线性表是否为空
		public boolean isEmpty() {
			return length == 0;
		}
		//返回线性表长度
		public int length() {
			return length;
		}
		//在线性表最后插入 x 元素
		public void add(T x) {
			add(length, x);
		}
		public void append(T x) {
			add(length, x);
		}
		public int indexOf(T o) {
			return indexOf(0, length, o)
		}
		public int indexOf(int begin, T o) {
			return indexOf(begin, length, o);
		}
		public T remove(T o) {
			return remove(indexOf(o));
		}
}

我们实现顺序表 SeqList 将继承 AbsList 抽象类,它的结构大致如下: 线性表

输入图片说明

下面是 SeqList.java 的代码

public class SeqList extends AbsList<T> implements Iterable<T> {
	//顺序表的增量长度,用于扩容
	private int incrementSize;
	//保存顺序表数据的数组
	protected T[] data;
	//默认构造函数
	public SeqList() {
		//顺序表默认长度设置为 16,后期可自动增加
		this(16);
	}
	//capacity 是顺序表的容量
	@SuppressWarings("unchecked")
	public SeqList(int capacity) {
		if(capacity <= 0)
			capacity = 16;
		//顺序表的长度设置为 0
		length = 0;
		//增量因子为 0
		incrementSize = 0;
		//Java 没有泛型数组,用 Object[] 数组代替,分配 16 个数组元素
		data = (T[])new Object[capacity];
	}
	//用数组 elem 初始化顺序表
	public SeqList(T[] elem) {
		length = elem.length;
		incrementSize = 0;
		data = elem;
	}
	public void setInc(int inc) {
		//设置顺序表每次容量增加时增量大小,默认值为 16
		incrementSize = inc;
	}
	//将顺序表的分配空间重新设置为 newSize
	public void setCapacity(int newSize) {
		data = Arrays.copyOf(data, newSize);
	}
	//设置长度
	public void setLength(int len) {
		if(len > data.length)
			grow();
		else if(len < 0)
			len = 0;
		length = len;
	}
	//获取顺序表的长度,同 size() ,为了方便
	public int size() {
		return length;
	}
	//取得顺序表下标为 i 的元素,也就是 data[i]
	@Override
	public T get(int i) {
		if(i < 0 || i > length - 1)
			return null;
		return data[i];
	}
	//实现两个元素的比较
	private int compare(T a, T b) {
		if(a instanceOf Comparable &&
			b instanceOf Comparable);
			return ((Comparable)a).compareTo((Comparable)b);
		else
			return (a.toString().compareTo(b.toString()));
	}
	//交换下标为 i 的元素值
	public void swap(int i, int j) {
		T temp = data[i];
		data[i] = data[j];
		data[j] = temp;
	}
	//查找值为 o 的数据元素的下标,使用顺序查找算法
	@Override
	public int indexOf(int begin, int end, T o) {
		//判断 o 是否为空
		if(o == null) {
			for(int i = begin; i < end; i++) {
				if(data[i].equals(o))
					return i;
			}
		}
		else {
			for(int i = begin; i < end; i++) {
				//元素可以自定义 equals 函数
				if(data[i].equals(o))
					return i;
			}
		}
		return -1;
	}
	//取逻辑下标为 i 的元素,同 get(i)
	public T valueOf(int i) {
		return get(i);
	}
	//内部使用,自动增加顺序表的容量
	private void grow() {
		int newSize;
		if(incrementSize == 0)
			newSize = (int)(1.618 * length);
		else
			newSize = incrementSize + data.length;
		data = Arrays.copyOf(data, newSize);
	}
	//在位置 i 插入数据元素 x
	@Override
	public void add(int i, T x) {
		if(length == data.length)
			grow();
		if(i < 0)
			i = 0;
		if(i > length)
			i = length;
		//从最后一个元素开始到 i 都往后移一个位置
		for(int j = length - 1; j >= i; j--)
			data[j + 1] = data[j];
		data[i] = x;
		length++;
	}
	//以有序的方式向顺序表增加数据元素 x
	public void addSort(T x) {
		insertOrder(length, x);
		length++;
	}
	//对顺序表排序
	public void sort() {
		/*
		利用 insertOrder 函数,它有两个参数,end 为整型,表示下标为 i(包括i) 之前的元素被排序,x 类型为 T,表示下标为 i 的那个元素。先从顺序表第 1、2个元素开始排序,
		然后将1、2个元素排好序后再与第三个元素比较之后排序,依次类推,直到最后一个元素,这样顺序表就是排好序的顺序表,书里说这种方法就插入排序。也就是说以先前排好的顺序再与后一位元素比较排序,直到最后一个元素,得到一个排好序的顺序表。
		*/
		Iterator<T> itr = iterator();
		itr.next();
		int i = 1;
		for(; itr.hasNext();) {
			insertOrder(i, itr.next());
			i++;
		}
	}
	//内部使用,以有序方式插入数据元素 x
	protected void insertOrder(int end, T x) {
		//length 是线性表的长度,data.length 代表的是给 data 数组分配空间的长度
		if(length == data.length)
			grow();
		int k;
		for(k = end - 1; k >= 0; k--) {
			if(comapre(x, data[k]) < 0)
				data[k + 1] = data[k];
			else
				break;
		}
		data[k + 1] = x;
	}
	//删除下标为 i 的元素
	@Override
	public T remove(int i) {
		if(i < 0 || i > length - 1)
			throw new IndexOutOfBoundsException("下标越界 i = " + i);
		T olddata = (T)data[i];
		for(int j = i; j < length - 1; j++)
			data[j] = data[j + 1];
		data[--length] = null;
		return olddata;
	}
	//清除整个顺序表
	@Override
	public void clear() {
		// let gc do its work
		for(int i = 0; i < length; i++)
			//让 Java 虚拟机的垃圾收集器自动处理
			data[i] = null;
		length = 0;
	}
	//顺序表的最大容量
	public int getCapacity() {
		return data.length;
	}
	@Override
	public String toString() {
		StringBuilder strb = new StringBuilder("(");
		for(int i = 0; i < length - 1; i++)
			strb = strb.append(data[i].toString() + ",");
		strb = strb.append(data[length - 1].toString() + ")");
		return new String(strb);
	}
	//将顺序表转换为 object 数组
	public Object[] toArray() {
		return Arrays.copyOf(this.data, this.length);
	}
	//将顺序表转换为类型为 E 的数组
	public T[] toArray(T[] a) {
		if(a.length < length)
			//Make a new array of as runtime type,but my contents:
			return (T[])Arrays.copyOf(this.data, this.length);
		System.arraycopy(this.data, 0, a, 0, this.length);
		if(a.length > this.length)
			a[length] = null;
		return a;
	}
	/
	public Iterator<T> iterator() {
		return new MyIterator();
	}
	//内部类,迭代器
	class MyIterator implements Iterator<T> {
		private int index = 0;
		public boolean hasNext() {
			//只要在调用 next()后,index 自加,确保 index 不等于顺序表的长度
			return index != length;
		}
		@Override
		public T next() {
			//使用索引来获取 SeqList 中下标为 index的项
			return get(index++);
		}
		@Override
		public void remove() {
			//为实现这个方法
		}
	}
	//MyIterator end
	///
	/*
	*	@param args
	*/
	public static void main(String[] args) {
		SeqList<Integer> ms = new SeqList<Integer>();
		for(int i = 0; i < 10; i++)
			ms.add((int)(10 * (9 - i + 1)));
		System.out.println(ms);
		System.out.println(ms.get(2));
		System.out.println(ms.getCapacity());
		System.out.println(ms.length());
		System.out.println("indexOf:" + ms.indexOf(60));
		System.out.println("==========================");
		for(integer x: ms) {
			System.out.println(x + ",");
		}
		SeqList myseq = new SeqList(10);
		myseq.add(1);
		myseq.add("oldbiwang");
		myseq.add("王锐鹏");
		myseq.add(25.0);
		System.out.println();
		System.out.println(myseq);
		System.out.println(myseq.get(0).getClass());
		System.out.println(myseq.get(1).getClass());
		System.out.println(myseq.get(2).getClass());
		System.out.println(myseq.get(3).getClass());
		//测试一个简单的 pojo 的类 Person
		SeqList<Person> sp = new SeqList<Person>(10);
		Person p1 = new Person();
		p1.setName("1王锐鹏");
		p1.setSex("男");
		sp.add(p1);
		Person p2 = new Person();
		p2.setName("2张三");
		p2.setSex("男");
		sp.add(p2);
		Person p3 = new Person();
		p3.setName("3貂蝉");
		p3.setSex("女");
		sp.add(p3);
		Person p4 = new Person();
		p4.setName("4阿尔法");
		p4.setSex("男");
		sp.add(p4);
		Person p5 = new Person();
		p5.setName("5阿尔法");
		p5.setSex("男");
		//重写 equals 方法,name 和 sex 都相等才是相等
		System.out.println(sp.indexOf(p5));
		/*System.out.println(p1 instanceof Comparable);
		System.out.println(p2 instanceof Comparable);
		System.out.println(p3 instanceof Comparable);*/
		//注意要这样调用 sp.indexOf(p3); indexOf(p3);会报错
		System.out.println(sp.indexOf(p3));
		System.out.println("排序前:");
		System.out.println(sp);
		/*	Iterator<Person> itr = sp.iterator();
		System.out.print("( ");
		for(;itr.hasNext();){
			System.out.print("[" + itr.next() + "]" + " ");
		}
		System.out.println(" )"); */
		//System.out.println(sp.get(0));
		sp.sort();
		Person p6 = new Person();
		p6.setName("6欧比旺");
		p6.setSex("男");
		System.out.println("排序前:");
		System.out.println(sp);
		System.out.println(sp.length());
		System.out.println("有序添加元素:");
		sp.addSort(p6);
		System.out.println(sp.length());
		System.out.println(sp);
		//在下标i 为 3的地方增加元素
		sp.add(3, p5);
		System.out.println(sp);
		sp.sort();
		System.out.println(sp);
		//在表尾增加元素
		sp.add(p5);
		System.out.println(sp);
		//删除第一个 p5 元素
		sp.remove(p5);
		System.out.println(sp);
		sp.remove(p5);
		System.out.println(sp);
		//得到下标为 3 的元素
		System.out.println("下标为 3 的元素" + sp.get(3));
		//修改下标为 3  的元素
		sp.set(3, p5);
		System.out.println(sp);
		Object[] array = sp.toArray();
		for(int i = 0; i < array.length; i++) {
			System.out.println((Person)array[i]);
		}
		Person[] a = new Person[15];
		a = sp.toArray(a);
		System.out.println(a);
		for(int i = 0; i < a.length; i++) {
			System.out.println(a[i]);
		}
	}
}

下面给出 Person.java 的代码

package oldbiwang.ds;
public class Person implements Comparable<Person> {
	String name;
	String sex;
	public String getName() {
		return name;
	}
	public void setName(String name)  {
		this.name = name;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public String toString() {
		return "name: " + name + " sex: " + sex;
	}
	@Override
	//实现 compareTo 方法
	public int compareTo(Person o) {
		if(name.compareTo(o.name) < 0)
			return -1;
		else
			return 1;
	}
	/*
	public boolean equals(Person o) {
		System.out.println("equals in");
		if(name.equals(o.name) && sex.equals(o.sex))
			return true;
		else
			return false;
	}*/
	@Override
	public boolean equals(Object o) {
		//System.out.println("equals in");
		if(name.equals(((Person)o).name) && sex.equals(((Person)o).sex))
			return true;
		else
			return false;
	}
}

至此顺序表的基本功能实现和测试基本完成,要附加功能的话也可以随时增加,比较复杂的是顺序的排序,领会插入排序的实现,还有一个就是迭代器的实现和使用,它可以屏蔽顺序表内部的实现细节,提供一个接口。

我们将实现链表 LinkList 将继承 AbsList 抽象类,它的结构大致如下: 线性表

输入图片说明

我们将用一个类 Lnode 来表示链表的结点 Lnode.java 的实现代码如下:

package oldbiwang.ds;
//链表节点
public class Lnode<T> implements Comparable<Lnode<T>> {
	//数据域
	public T data;
	//指针域,指向下一个元素
	public Lnode<T> next;
	public Lnode(T key) {
		data = key;
		next = null;
	}
	public Lnode(T key, Lnode<T> e) {
		data = key;
		next = e;
	}
	public boolean equals(Object e) {
		Lnode<T> node = (Lnode<T>)e;
		return data.equals(node.data);
	}
	//实现 Comparable 接口的 compareTo 方法
	public int compareTo(Lnode<T> e) {
		Comparable<T> x;
		if(data instanceof Comparable) {
			x = (Comparable)data;
			return (int)x.compareTo(e.data);
		}
		else
			throw new ClassCastException("类型无法比较!");
	}
	public String toString() {
		return data.toString();
	}
}

接下来是链表的 Java 实现,LinkList.java 如下:

package oldbiwang.ds;
import java.util.Iterator;
public class LinkList<T> extends AbsList<T> implements Iterable<T> {
	//指向表头的头指针
	Lnode<T> first;
	//指向表尾的尾指针
	Lnode<T> last;
	//当前指针 写的时候忘了
	Iterator<T> itr = null;
	//默认构造函数
	public LinkList() {
		first = last = null;
		length = 0;
		//写的时候忘记了
		itr = new LinkIterator();
	}
	//写的时候忘了
	//比较两个结点的大小
	private int compare(Lnode<T> a,Lnode<T> b) {
		return a.compareTo(b);
	}
	//清除操作
	public void clear() {
		first = last = null;
		length = 0;
	}
	//写的时候忘了
	public int length() {
		return length;
	}
	//写的时候忘了
	public int size() {
		return length;
	}
	//得到第 i 个元素,从 0 开始计数
	public Lnode<T> getNode(int i) {
		if(i < 0 || i > length - 1)
			return null; //忘记判断
		//忘记判断头结点
		if(i == 0)
			return first;
		Lnode<T> p = first;
		int j = 0;
		while(p != null && j < i) {
			p = p.next;
			j++;
		}
		return p;
	}
	//得到第 i 个元素的值
	public T get(int i) {
		Lnode<T> node = getNode(i);
		if(node != null)
			return node.data;
		else
			return null;
	}
	//修改第 i 个元素的值,从 0 开始计数
	public boolean set(int i, T x) {
		Lnode<T> node = getNode(i);
		if(node != null) {
			node.data = x;
			return true;
		}
		else
			return false;
	}
	//增加结点操作
	public void add(int i, T o) {
		Lnode<T> p;
		Lnode<T> node = new Lnode<T>(o, null);
		int j = i - 1;
		//忘记写 length == 0
		if(first == null || length == 0) {
			//在空链表中插入结点 node
			first = node;
			last = node;
		}
		else if(j < 0) {
			//在头结点之前插入结点 node
			node.next = first;
			first = node;
		}
		else if(j >= length - 1) {
			//在尾结点之后插入 结点node
			last.next = node;
			last = node;
		}
		else{
			//在链表中间插入结点 s
			p = getNode(j);
			node.next = p.next;
			p.next = node;
		}
		length++;
	}
	/*//我写的增加结点操作,有一些错误与冗余
	public void add(int i, T o) {
		Lnode<T> node = new Lnode<T>(o, null);
		int j = i - 1;
		if(first == null) {
			first = node;
			last = node;
			length++;
			return;
		}
		if(i <= 0) {
			node.next = first;
			first = node;
			length++;
			return;
		}
		if(i > 0 && i < length) {
			Lnode<T> p = getNode(j);
			node.next = p.next;
			p.next = node;
			length++;
			return;
		}
		if(i >= length) {
			last.next = node;
			last = node;
			length++;
			return;
		}
	}*/
	//下面三个 add 方法写的时候都忘记写了
	public void add(T key) {
		add(length, key);
	}
	public void addBack(T key) {
		add(length, key);
	}
	public void addFront(T key) {
		add(0, key);
	}
	//这个写的时候没思路
	public void sort() {
		LinkList<T> sl = new LinkList<T>();
		Lnode<T> p;
		p = this.removeNode(0);
		while(p != null) {
			sl.insertOrder(p);
			p = this.removeNode(0);
		}
		this.first = sl.first;
		this.last = sl.last;
		this.length = sl.length;
	}
	//这个方法我已经忘记
	public void addSort(T e) //throws NoComparatorOfType
	{
		Lnode<T> s = new Lnode<T>(e, null);
		insertOrder(s);
	}
	private void insertOrder(Lnode<T> s) //throws NoComparatorOfType
	{
		Lnode<T> p1,p2;
		length = length + 1;
		if(first == null) {
			//空链表
			first = s;
			last = first;
			return;
		}
		if(compare(s, first) < 0) {
			s.next = first;
			first = s;
			return;
		}
		if(compare(s,last) >= 0) {
			last.next = s;
			last = s;
			return;
		}
		//被插结点 p 在 p1 和 p2 之前
		p2 = first;
		p1 = p2;
		while(p2 != null) {
			if(compare(s, p2) > 0) {
				p1 = p2;
				p2 = p2.next;
			}
			else
				break;
		}
		s.next = p2;
		p1.next = s;
		return;
	}
	///
	public void removeAll() {
		clear();
	}
	//写的时候忘记了
	public T remove(int i) {
		Lnode<T> p = removeNode(i);
		if(p != null)
			return p.data;
		else
			return null;
	}
	//删除结点第 i 号结点,从 0 开始计数
	public Lnode<T> removeNode(int i) {;
		Lnode<T> p,q;
		if(first == null)
			return null;
		if(i == 0) {
			p = first;
			first = first.next;
			length = length - 1;
			return p;
		}
		if(i >= 1 && i <= length - 1) {
			 p = getNode(i - 1);
			 q = p.next;
			 p.next = q.next;
			 if(q == last) {
				 last = p;
			 }
			 return q;
		}
		return null;
	}
	//下面三个方法写的时候忘记了
	public T removeFront() {
		return removeNode(0).data;
	}
	public T removeBack() {
		return removeNode(length - 1).data;
	}
	public T remove() {
		return removeNode(0).data;
	}
	public int indexOf(int begin, int end, T key) {
		Lnode<T> p = getNode(begin);
		int i = begin;
		while(p != null && i < end) {
			if(p.data.equals(key))
				return i;
			p = p.next;
			i++;
		}
		return -1;
	}
	//写的时候忘记了
	public T search(T key) {
		Lnode<T> p =  getNode(0);
		while(p != null) {
			if(p.data.equals(key))
				return p.data;
			p = p.next;
		}
		return null;
	}
	//写的时候忘记了
	public boolean contains(T key) {
		if(indexOf(key) == -1)
			return false;
		else
			return true;
	}
	public String toString() {
		Lnode<T> p = first;
		if(p == null)
			return "(  )";
		String str = "(";
		while(p != null)
		{
			if(p == last) {
					str = str + p.data.toString() + ")";
					break;
			}
			else
				str = str + p.data.toString() + "->";
			p = p.next;
		}
		return str;
	}
	public Object[] toArray() {
		Object[] a = new Object[length];
		Lnode<T> p = first;
		for(int i=0;i<length;i++) {
			a[i] = p.data;
			p = p.next;
		}
		return a;
	}
	@SuppressWarnings("unchecked")
	public <E> E[] toArray(E[] a) {
		if(a.length < length)
			a = (E[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(),length);
		int i = 0;
		Object[] result = a;
		Lnode<T> x = this.first;
		for(i = 0; i < length; i++) {
			result[i] = x.data;
			x = x.next;
		}
		if(a.length < length)
			a[length] = null;
		return a;
	}
	public Iterator<T> iterator() {
		this.itr = new LinkIterator();
		return this.itr;
	}
	//内部类,迭代器
	private class LinkIterator implements Iterator<T> {
		private int index = 0;
		private Lnode<T> current = first;
		public boolean hasNext() {
			//只要在调用next()后,index自加,确保
			return (index != length() &&
			current != null);
		}
		@Override
		public T next() {
			T temp = current.data;
			current = current.next;
			index++;
			return temp;
		}
		public int nextIndex() {
			return index++;
		}
		@Override
		public void remove() {
			//未实现这个方法
		}
	}
	public static void main(String[] args) {
		LinkList<Person> linkList = new LinkList<Person>();
		Person p1 = new Person();
		p1.setName("Obiwan");
		p1.setSex("male");
		linkList.add(p1);
		Person p2 = new Person();
		p2.setName("Yoda");
		p2.setSex("male");
		linkList.add(p2);
		Person p3 = new Person();
		p3.setName("Vader");
		p3.setSex("male");
		linkList.add(p3);
		Person p4 = new Person();
		p4.setName("Lisa");
		p4.setSex("female");
		linkList.add(p4);
		System.out.println(linkList);		
		//排序
		System.out.println("排序后");
		linkList.sort();
		System.out.println(linkList);
		//方法一:迭代器使用 foreach 输出
		System.out.println("foreach 输出:");
		for(Person p : linkList)
			System.out.println(p);
		//方法二:迭代器使用 while 和 iterator 循环输出
		System.out.println("iterator 输出:");
		Iterator<Person> itr = linkList.iterator();
		while(itr.hasNext()) {
			System.out.println(itr.next() + " ");
		}
		System.out.println("\n===============================");
		System.out.println("length = " + linkList.length());
		System.out.println("size = " + linkList.size());
		Person p5 = new Person();
		p5.setName("Obiwan");
		p5.setSex("male");
		System.out.println("contains p5: " + linkList.contains(p5));
		System.out.println("p5 index of: " + linkList.indexOf(p5));
		System.out.println("search p5: " + linkList.search(p5));
		Person p6 = new Person();
		p6.setName("Oldbiwang");
		p6.setSex("male");
		linkList.addSort(p6);
		System.out.println("addSort: " + linkList);
		System.out.println("===============================\n");
		System.out.println("===============================");
		Person p7 = new Person();
		p7.setName("Luke");
		p7.setSex("male");
		System.out.println("before addFront: " + linkList);
		linkList.addFront(p7);
		System.out.println("after addFront: " + linkList);
		linkList.addBack(p7);
		System.out.println("after addBack: " + linkList);
		Person pGet = linkList.get(3);
		System.out.println("pGet: " + pGet);
		System.out.println("after Get:" + linkList);
		linkList.set(linkList.length() - 1,p1);
		System.out.println("after set:" + linkList);
		linkList.remove(linkList.size() - 1);
		System.out.println("after remove: " + linkList);
		System.out.println("再次排序");
		linkList.sort();
		System.out.println(linkList);
		System.out.println("===============================\n");
		System.out.println("toObjectArray");
		Object[] o = linkList.toArray();
		for(Object person : o) {
			System.out.println("person: " + (Person)person);
		}
		System.out.println("to E Array");
		//Person[] e = new Person[4];输出都为空.所以数组长度要大于链表长度
		Person[] e = new Person[10];
		linkList.toArray(e);
		for(int i = 0; i < e.length; i++) {
			System.out.println("person: " + e[i]);
		}
	}
}

链表的基本实现和测试也基本完成,使用的也是 pojo Person 类,链表的排序比较简单,新创建一个链表,将没排序链表的值插入进去,最后得到一个排好序的链表再返回来。链表是链式存储,也就是在内存里的位置地址不是连续的,而是分散的。

总结:顺序表和链表都是线性表的实现,它们各有优点,各有缺点。如果是经常改变的结构,如插入、删除等操作比较频繁的,使用链表好一点。如果对于不经常改变,查询和修改元素值比较多的结构,就多使用顺序表。

转载于:https://my.oschina.net/oldbiwang/blog/1538669

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值