java数据结构--线性结构
一、数据结构
数据结构由数据和结构两部分组成,就是将数据按照一定的结构组合起来,这样不同的组合方式有不同的效率,可根据需求选择不同的结构应用在相应在场景。数据结构大致
分为两类:线性结构(如数组,链表,队列,栈等),非线性结构(如树,图,表等)。本文介绍下线性结构,下章介绍非线性结构。
二、数组
数组表示一组有限个相同类型的数据的集合,顺序存储,下标从0开始,其特点是可以根据下标快速的查找到元素,但在增加和删除元素时会导致大量的数据位置的变动,即这
种情况下性能不高,故数组一般多用于查找频繁,增,删较少的情况。
下图为一个二维数组的结构图:
插入元素:
当往数组某位置上插入元素时,需要将位置后的所有元素往后移动一个位置。
删除元素:
当删除数组上的某个元素时,需要将该元素后的所有元素的位置往前移动一个位置。
下面简单实现数组中插入元素和删除元素功能:
public class ArrayDemo<T> {
	private Object[] array ;
	private int length = 0;
	private final static int DEFAULT_CAPACITY = 10;
	public ArrayDemo(){
		super();
		this.array = new Object[DEFAULT_CAPACITY];
		this.length = DEFAULT_CAPACITY;
	}
	public ArrayDemo(int length){
		super();
		if(length < 0){
			throw new IllegalArgumentException("error length:"+length);
		}
		this.array = new Object[length];
		this.length = length;
	}
	public ArrayDemo(Collection<? extends T> c){
		array = c.toArray();
		length = c.size();
		if(array.getClass() != Object[].class){
			array = Arrays.copyOf(array, length, Object[].class);
		}
	}
	/**
	 * 在数组array的index位置处插入一个元素t,如果已经满了,则移除最后一个元素
	 * @param array
	 * @param t
	 * @param indext
	 */
	public void insert(T t, int index){
		if(null == t){
			throw new NullPointerException("null Pointer!");
		}
		if(index < 0 || index > length-1){
			throw new IndexOutOfBoundsException("index is error");
		}
		for(int pos = length-1; pos>index; pos--){
			array[pos] = array[pos-1];
		}
		array[index] = t;
	}
	/**
	 * 删除指定位置上的数组元素
	 * @param array
	 * @param index
	 */
	public void delete(int index){
		if(null == array){
			throw new NullPointerException("null Pointer!");
		}
		int length = array.length;
		if(index < 0 || index > length-1){
			throw new IndexOutOfBoundsException("index is error");
		}
		for(int pos = index; pos < length-1; pos++){
			array[pos] = array[pos+1];
		}
		array[length-1] = null;
	}
	/**
	 * 遍历输出数组中所有元素
	 */
	public void trans(){
		if(null == array){
			throw new NullPointerException("null Pointer!");
		}
		for(int pos=0; pos< length; pos++){
			System.out.println(array[pos]);
		}
	}
}
public class Person {
	private String name;
	private 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;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", sex=" + sex + "]";
	}
	public Person(String name, String sex) {
		super();
		this.name = name;
		this.sex = sex;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		result = prime * result + ((sex == null) ? 0 : sex.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (sex == null) {
			if (other.sex != null)
				return false;
		} else if (!sex.equals(other.sex))
			return false;
		return true;
	}
}
测试类:
public class TestArray {
	public static void main(String[] args) {
		ArrayDemo<Person> array = new ArrayDemo<>();
		Person p = new Person("张三", "m");
		array.insert(p, 0);
		array.trans();
		array.delete(0);
		System.out.println("---");
		array.trans();
	}
}
三、链表
链表是一种有序的列表。链表的内容通常存储在内存中分散的位置上。链表由节点组成,每个节点的结构都是相同的。节点分为数据域和链域,数据域顾名思义,就是存放节点
节点的内容,链域存放的是下一个节点的指针或引用。如果是双向链表的话,链域中还会有前一个节点的指针或引用。下图为单向链表各节点间的关系图。
下面来实现一个简单的链表结构
节点类:
public class Node<T> {
	private T data;
	private Node<T> pre;
	private Node<T> next;
	public Node(){
		super();
		this.pre = null;
		this.next = null;
	}
	public Node(T data){
		super();
		this.data = data;
		this.pre = null;
		this.next = null;
	}
	public Node(T data, Node<T> pre, Node<T> next){
		super();
		this.data = data;
		this.pre = pre;
		this.next = next;
	}
	public T getData() {
		return data;
	}
	public void setData(T data) {
		this.data = data;
	}
	public Node<T> getPre() {
		return pre;
	}
	public void setPre(Node<T> pre) {
		this.pre = pre;
	}
	public Node<T> getNext() {
		return next;
	}
	public void setNext(Node<T> next) {
		this.next = next;
	}
}
链表类
public class LinkedListDemo<T> {
	private Node<T> head;//头结点
	private Node<T> tail;//尾节点
	private int size;//链表大小
	public LinkedListDemo(){
		head = new Node<T>(null, null, null);
		tail = new Node<T>(null, head, null);
		head.setNext(tail);
		size = 0;
	}
	public MyIterator<T> iterator(){
		return new MyIterator<T>();
	}
	public void add(T data){
		Node<T> node = new Node<T>(data);
		node.setPre(tail.getPre());
		tail.getPre().setNext(node);
		tail.setPre(node);
		node.setNext(tail);
		size++;
	}
	public void remove(T data){
		Node<T> node = head;
		while(tail != node.getNext()){
			Node<T> currentNode = node.getNext();
			if(currentNode.getData().equals(data)){
				currentNode.getPre().setNext(currentNode.getNext());
				currentNode.getNext().setPre(currentNode.getPre());
				size--;
				break;
			}
			node = currentNode;
		}
	}
	public void print(){
		Node<T> node = head;
		while(tail != node.getNext()){
			Node<T> currentNode = node.getNext();
			System.out.println(currentNode.getData().toString());
			node = currentNode;
		}
	}
	/**
	 *
	 * 项目名: adt
	 * 类名: LinkedListDemo.java
	 * 类描述: 定义一个该链表的迭代器来访问
	 * 备注:
	 * 创建日期:2014-10-10
	 * 创建时间:上午12:10:46
	 * @param <T>
	 */
	@SuppressWarnings("hiding")
	private class MyIterator<T> implements Iterator<T>{
		@SuppressWarnings("unchecked")
		private Node<T> currentNode = (Node<T>) head.getNext();//节点读取当前位置
		private Node<T> returnedNode = currentNode;//返回节点的位置
		@Override
		public boolean hasNext() {
			return currentNode == tail? false:true;
		}
		@Override
		public T next() {
			if(!hasNext()){
				throw new IndexOutOfBoundsException();
			}
			returnedNode = currentNode;
			currentNode = currentNode.getNext();
			return returnedNode.getData();
		}
		@Override
		public void remove() {
			if(!hasNext()){
				throw new NoSuchElementException();
			}
			returnedNode.getPre().setNext(returnedNode.getNext());
			returnedNode.getNext().setPre(returnedNode.getPre());
			returnedNode = returnedNode.getNext();
			currentNode = returnedNode;
			size--;
		}
	}
}
测试类:
public class TestDemo {
	public static void main(String[] args) {
		LinkedListDemo<Person> list = new LinkedListDemo<Person>();
		//往链表中加入10个元素
		for(int i=0; i<10;i++){
			Person p = new Person("zhang"+i, "m");
			list.add(p);
		}
		list.print();
		System.out.println("========");
		Person p = new Person("zhang1", "m");
		list.remove(p);//移除自定的元素
		list.print();
		System.out.println("========");
		Person p1 = new Person("zhang4", "m");
		Iterator<Person> iterator = list.iterator();
		while(iterator.hasNext()){
			Person person = iterator.next();
			if(person.equals(p1)){
				iterator.remove();//迭代器移除制定元素
				break;
			}
		}
		list.print();
	}
}
结果:
Person [name=zhang0, sex=m]
Person [name=zhang1, sex=m]
Person [name=zhang2, sex=m]
Person [name=zhang3, sex=m]
Person [name=zhang4, sex=m]
Person [name=zhang5, sex=m]
Person [name=zhang6, sex=m]
Person [name=zhang7, sex=m]
Person [name=zhang8, sex=m]
Person [name=zhang9, sex=m]
========
Person [name=zhang0, sex=m]
Person [name=zhang2, sex=m]
Person [name=zhang3, sex=m]
Person [name=zhang4, sex=m]
Person [name=zhang5, sex=m]
Person [name=zhang6, sex=m]
Person [name=zhang7, sex=m]
Person [name=zhang8, sex=m]
Person [name=zhang9, sex=m]
========
Person [name=zhang0, sex=m]
Person [name=zhang2, sex=m]
Person [name=zhang3, sex=m]
Person [name=zhang5, sex=m]
Person [name=zhang6, sex=m]
Person [name=zhang7, sex=m]
Person [name=zhang8, sex=m]
Person [name=zhang9, sex=m]
四、队列
队列数据结构类似于生活中队列,有一个很重要的特性:先进先出。即增加元素肯定是在队列的尾部添加,删除元素肯定是删除队列头部的元素。队列的实现可以用数据结构,
也可以用链表结构。
下面简单是一个用数组结构实现的队列结构:
public class QueueDemo<T> {
	private Object[] object;
	/**
	 * 队列容量
	 */
	private int capicity;
	/**
	 * 队列中元素的个数
	 */
	private int size;
	private final static int DEFAULT_CAPICAL = 10;
	public QueueDemo(){
		capicity = DEFAULT_CAPICAL;
		object = new Object[capicity];
	}
	public QueueDemo(int capicity){
		this.capicity = capicity;
		object = new Object[this.capicity];
	}
	public int size(){
		return size;
	}
	public boolean isEmpty(){
		return size==0;
	}
	/**
	 * 往队列中添加元素
	 * @param t
	 */
	public void add(T t){
		if(size == capicity){
			throw new IndexOutOfBoundsException("queue is full");
		}
		object[size++]=t;
	}
	/**
	 * 移除队列中的元素
	 */
	public void remove(){
		if(isEmpty()){
			throw new IndexOutOfBoundsException("queue is empty");
		}
		for(int pos = 0; pos < size-1; pos++){//将整个数组往前以一个位置
			object[pos] = object[pos+1];
		}
		size--;
	}
	public void clear(){
		Arrays.fill(object, null);
		size=0;
	}
	public void print(){
		for(int i=0; i<size; i++){
			System.out.println(object[i].toString());
		}
	}
}
测试类:
public class TestQueue {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		QueueDemo<Person> queue = new QueueDemo<Person>();
		for(int i=0; i<10; i++){
			Person p = new Person("zhang"+i, "m");
			queue.add(p);
		}
		queue.print();
		System.out.println("=====");
		while(queue.size() > 0){//依次删除队列头元素
			queue.remove();
			queue.print();
			System.out.println("=====");
		}
	}
}
输出:
Person [name=zhang0, sex=m]
Person [name=zhang1, sex=m]
Person [name=zhang2, sex=m]
Person [name=zhang3, sex=m]
Person [name=zhang4, sex=m]
Person [name=zhang5, sex=m]
Person [name=zhang6, sex=m]
Person [name=zhang7, sex=m]
Person [name=zhang8, sex=m]
Person [name=zhang9, sex=m]
=====
Person [name=zhang1, sex=m]
Person [name=zhang2, sex=m]
Person [name=zhang3, sex=m]
Person [name=zhang4, sex=m]
Person [name=zhang5, sex=m]
Person [name=zhang6, sex=m]
Person [name=zhang7, sex=m]
Person [name=zhang8, sex=m]
Person [name=zhang9, sex=m]
=====
Person [name=zhang2, sex=m]
Person [name=zhang3, sex=m]
Person [name=zhang4, sex=m]
Person [name=zhang5, sex=m]
Person [name=zhang6, sex=m]
Person [name=zhang7, sex=m]
Person [name=zhang8, sex=m]
Person [name=zhang9, sex=m]
=====
Person [name=zhang3, sex=m]
Person [name=zhang4, sex=m]
Person [name=zhang5, sex=m]
Person [name=zhang6, sex=m]
Person [name=zhang7, sex=m]
Person [name=zhang8, sex=m]
Person [name=zhang9, sex=m]
=====
Person [name=zhang4, sex=m]
Person [name=zhang5, sex=m]
Person [name=zhang6, sex=m]
Person [name=zhang7, sex=m]
Person [name=zhang8, sex=m]
Person [name=zhang9, sex=m]
=====
Person [name=zhang5, sex=m]
Person [name=zhang6, sex=m]
Person [name=zhang7, sex=m]
Person [name=zhang8, sex=m]
Person [name=zhang9, sex=m]
=====
Person [name=zhang6, sex=m]
Person [name=zhang7, sex=m]
Person [name=zhang8, sex=m]
Person [name=zhang9, sex=m]
=====
Person [name=zhang7, sex=m]
Person [name=zhang8, sex=m]
Person [name=zhang9, sex=m]
=====
Person [name=zhang8, sex=m]
Person [name=zhang9, sex=m]
=====
Person [name=zhang9, sex=m]
=====
=====
五、栈
栈结构与队列类似,不过区别在于栈是先进后出的。即最先进栈的元素是最后一个出栈的。栈的结构也可以用数组或链表来实现。
下面简单实现一个基于数组结构的栈,实现只是稍微修改下上面队列结构的代码。
public class StackDemo<T> {
	private Object[] object;
	private int capicity;
	private int size;
	private final static int DEFAULT_CAPICAL = 10;	
	public StackDemo(){
		capicity = DEFAULT_CAPICAL;
		object = new Object[capicity];
	}
	public StackDemo(int capicity){
		this.capicity = capicity;
		object = new Object[this.capicity];
	}
	public int size(){
		return size;
	}
	public boolean isEmpty(){
		return size==0;
	}
	public void add(T t){
		if(size == capicity){
			throw new IndexOutOfBoundsException("queue is full");
		}
		object[size++]=t;
	}
	/**
	 * 修改移除元素的代码
	 */
	public void remove(){
		if(isEmpty()){
			throw new IndexOutOfBoundsException("queue is empty");
		}
		object[--size]=null;
	}
	public void clear(){
		Arrays.fill(object, null);
		size=0;
	}
	public void print(){
		for(int i=0; i<size; i++){
			System.out.println(object[i].toString());
		}
	}
}
测试类:
public class TestStack {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		StackDemo<Person> queue = new StackDemo<Person>();
		for(int i=0; i<10; i++){
			Person p = new Person("zhang"+i, "m");
			queue.add(p);
		}
		queue.print();
		System.out.println("=====");
		while(queue.size() > 0){
			queue.remove();
			queue.print();
			System.out.println("=====");
		}
	}
}
结果:
Person [name=zhang0, sex=m]
Person [name=zhang1, sex=m]
Person [name=zhang2, sex=m]
Person [name=zhang3, sex=m]
Person [name=zhang4, sex=m]
Person [name=zhang5, sex=m]
Person [name=zhang6, sex=m]
Person [name=zhang7, sex=m]
Person [name=zhang8, sex=m]
Person [name=zhang9, sex=m]
=====
Person [name=zhang0, sex=m]
Person [name=zhang1, sex=m]
Person [name=zhang2, sex=m]
Person [name=zhang3, sex=m]
Person [name=zhang4, sex=m]
Person [name=zhang5, sex=m]
Person [name=zhang6, sex=m]
Person [name=zhang7, sex=m]
Person [name=zhang8, sex=m]
=====
Person [name=zhang0, sex=m]
Person [name=zhang1, sex=m]
Person [name=zhang2, sex=m]
Person [name=zhang3, sex=m]
Person [name=zhang4, sex=m]
Person [name=zhang5, sex=m]
Person [name=zhang6, sex=m]
Person [name=zhang7, sex=m]
=====
Person [name=zhang0, sex=m]
Person [name=zhang1, sex=m]
Person [name=zhang2, sex=m]
Person [name=zhang3, sex=m]
Person [name=zhang4, sex=m]
Person [name=zhang5, sex=m]
Person [name=zhang6, sex=m]
=====
Person [name=zhang0, sex=m]
Person [name=zhang1, sex=m]
Person [name=zhang2, sex=m]
Person [name=zhang3, sex=m]
Person [name=zhang4, sex=m]
Person [name=zhang5, sex=m]
=====
Person [name=zhang0, sex=m]
Person [name=zhang1, sex=m]
Person [name=zhang2, sex=m]
Person [name=zhang3, sex=m]
Person [name=zhang4, sex=m]
=====
Person [name=zhang0, sex=m]
Person [name=zhang1, sex=m]
Person [name=zhang2, sex=m]
Person [name=zhang3, sex=m]
=====
Person [name=zhang0, sex=m]
Person [name=zhang1, sex=m]
Person [name=zhang2, sex=m]
=====
Person [name=zhang0, sex=m]
Person [name=zhang1, sex=m]
=====
Person [name=zhang0, sex=m]
=====
=====
六、几种简单的线性结构介绍完了,在实际的应用环境中需要参考各种数据结构的特点来选择。
数组:查找速度很快,但长度固定,增,删效率较低。
链表:增删效率较高,长度不固定,但查找需要从头遍历整个链表,效率较低。
队列:可用数组,链表实现,先进先出。
栈:可用数组,链表实现,先进后出。
java数据结构--线性结构的更多相关文章
- Java数据结构-线性表之单链表LinkedList
		线性表的链式存储结构,也称之为链式表,链表:链表的存储单元能够连续也能够不连续. 链表中的节点包括数据域和指针域.数据域为存储数据元素信息的域,指针域为存储直接后继位置(一般称为指针)的域. 注意一个 ... 
- Java数据结构-线性表之顺序表ArrayList
		线性表的顺序存储结构.也称为顺序表.指用一段连续的存储单元依次存储线性表中的数据元素. 依据顺序表的特性,我们用数组来实现顺序表,以下是我通过数组实现的Java版本号的顺序表. package com ... 
- java数据结构-非线性结构之树
		一.树状图 树状图是一种数据结构,它是由n(n>=1)个有限节点组成的具有层次关系的集合.因其结构看起来想个倒挂的树,即根朝上,叶子在下,故被称为"树". 特点: 1. 每个 ... 
- Java数据结构-线性表之静态链表
		静态链表的定义: 节点由一个一维数组和一个指针域组成,数组用来存放数据元素,而指针域里面的指针(又称游标)用来指向下一个节点的数组下标. 这种链表称之为静态链表. 链表中的数组第一个和最后一个位置须要 ... 
- Java数据结构和算法(四)赫夫曼树
		Java数据结构和算法(四)赫夫曼树 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 赫夫曼树又称为最优二叉树,赫夫曼树的一个 ... 
- 【Java数据结构学习笔记之一】线性表的存储结构及其代码实现
		应用程序后在那个的数据大致有四种基本的逻辑结构: 集合:数据元素之间只有"同属于一个集合"的关系 线性结构:数据元素之间存在一个对一个的关系 树形结构:数据元素之间存在一个对多个关 ... 
- Java数据结构和算法(一)线性结构之单链表
		Java数据结构和算法(一)线性结构之单链表 prev current next -------------- -------------- -------------- | value | next ... 
- Java数据结构和算法(一)线性结构
		Java数据结构和算法(一)线性结构 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 线性表 是一种逻辑结构,相同数据类型的 ... 
- Java数据结构介绍(线性结构和非线性结构)
		数据结构包括:线性结构和非线性结构. 线性结构 数据元素之间存在一对一的线性关系 包括顺序存储结构和链式存储结构.顺序存储的线性表称为顺序表,顺序表中的存储元素是连续的 链式存储的线性表称为链表,链表 ... 
随机推荐
- gulp最佳实践(包含js,css,html预编译,合并,压缩,浏览器自动刷新)
			gulp是基于流的自动化构建工具官方网址:http://www.gulpjs.com.cn/ 一.安装需要的模块 1.新建package.json,输入下面的内容 { "name" ... 
- Python小杂点
			1.函数调用 a = [] def fun(a): a.append(1) print (a) 这个时候输出的结果为[],如果想要出现1,需要先运行函数fun,然后在输出a 2.python方法 de ... 
- Codeforces Round #336 (Div. 1) A - Chain Reaction
			Chain Reaction 题意:有n(1 ≤ n ≤ 100 000) 个灯泡,每个灯泡有一个位置a以及向左照亮的范围b (0 <= a <= 1e6 ,1<= b <= ... 
- ARM中的PC和AXD的PC
			R15 (PC)总是指向“正在取指”的指令,而不是指向“正在执行”的指令或正在“译码”的指令.一般来说,人们习惯性约定将“正在执行的指令作为参考点”,称之为当前第一条指令,因此PC 总是指向第三条指令 ... 
- C++ 11 笔记 (四) : std::bind
			std::bind 接受一个可调用的对象,一般就是函数呗.. 还是先上代码: void func(int x, int y, int z) { std::cout << "hel ... 
- C++ 11 笔记 (一) : lambda
			时至今日都是我咎由自取,错就是错,与任何人无关.掉进C++98的各种坑里无法自拔的抖M感,让我选择了华丽丽的无视C++11,导致今日面对开源的代码到各种看不懂的地步,一入C++深似海,我今天愿意承担一 ... 
- 利用Jquery实现http长连接(LongPoll)
			参考:http://www.cnblogs.com/vagerent/archive/2010/02/05/1664450.html PS:为了满足 某些需要 实时请求的业务(PS:例如聊天室),我们 ... 
- FFMPEG视音频编解码零基础学习方法-b
			感谢大神分享,虽然现在还看不懂,留着大家一起看啦 PS:有不少人不清楚“FFmpeg”应该怎么读.它读作“ef ef em peg” 0. 背景知识 本章主要介绍一下FFMPEG都用在了哪里(在这里仅 ... 
- JAVA 反射特性
			1. 反射(概念):程序在运行期可以改变程序结构和变量类型,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力. 2. 反射的特性: •在运行时判断任意一个对象所属的类 •在运行时构造 ... 
- css3加载中
			.loader { margin: 6em auto; font-size: 10px; position: relative; text-indent: -9999em; border-top: 1 ... 
