zoukankan      html  css  js  c++  java
  • 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]
    =====
    =====

    六、几种简单的线性结构介绍完了,在实际的应用环境中需要参考各种数据结构的特点来选择。

    数组:查找速度很快,但长度固定,增,删效率较低。

    链表:增删效率较高,长度不固定,但查找需要从头遍历整个链表,效率较低。

    队列:可用数组,链表实现,先进先出。

    栈:可用数组,链表实现,先进后出。


  • 相关阅读:
    WebCollector2.7爬虫框架——在Eclipse项目中配置
    JavaScript 输出
    CSS3 页面中展示邮箱列表点击弹出发送邮件界面
    CSS3 Flex Box(弹性盒子)
    CSS 分页实例
    CSS 图片
    CSS3 用户界面
    CSS3 动画
    CSS3 过渡
    CSS3 3D转换
  • 原文地址:https://www.cnblogs.com/marcotan/p/4256902.html
Copyright © 2011-2022 走看看