Java实现数据结构----线性表,单链表

线性表

线性表是n个类型相同的数据元素的有限序列,通常记作(a0,a1,a2…an)、

特点:

  • 线性结构作为最常用的数据结构,其特点是数据元素之间存在一对一的线性关系
  • 线性结构有两种不同存储结构,即,顺序结构(数组)和链式结构(链表),顺序存储的线性表为顺序表,顺序表中的存储元素是连续的
  • 链式存储的现行表成为链表,链表中的储存元素不一定是连续的,元素节点中存放的数据元素以及相邻元素的地址信息
     接口信息
     
public interface Liner {
 //获取表大小,即数据元素的个数
	public int size();
	//判断是否为空
	public boolean isEmpty();
	//获取
	public Object get(int i);
	
	//判断线性表是否包括数据元素obj
	public boolean contains(Object obj);
	//返回数据元素obj在线性表中的序号
	public int indexOf(Object obj);
	//将元素obj插入到线性表末尾
	public void add(Object index);
	//将元素obj插入到index位置
	public void add(int index,Object obj);
	//删除序号为index的元素
	public Object remove(int index) ;
}



    自定义异常
    
public class MyArrayIndexOutOfBoundsException extends RuntimeException{

	public MyArrayIndexOutOfBoundsException() {
		super();
		// TODO Auto-generated constructor stub
	}

	public MyArrayIndexOutOfBoundsException(String message) {
		super(message);
		// TODO Auto-generated constructor stub
	}

}
   实现类
 
import java.util.ArrayList;
import java.util.Arrays;
public class LinerTable implements Liner {
	private Object[] elementData;// 底层是个数组,目前未分配长度
	private int size;// 不是数组分配的空间,是元素的个数

	public LinerTable() {
		// 没有指定长度,默认长度4
		this(4);
		// 没有指定长度,长度是0
		// elementData =new Object[]{};

	}

	/**
	 * @param initialCapacity
	 *            指定数组的初始长度
	 */
	public LinerTable(int initialCapacity) {
		// 给数组分配指定的数量的空间
		elementData = new Object[initialCapacity];
		// 指定顺序表的元素个数
		//
	}

	public int size() {
		return size;
	}

	public boolean isEmpty() {
		return size == 0;
	}

	public Object get(int i) {
		if (i < 0 || i >= size) {
			throw new MyArrayIndexOutOfBoundsException("数组索引越界异常" + i);
		}
		return elementData[i];
	}

	public boolean contains(Object obj) {
		if (isEmpty()) {
			return false;
		}
		for (int i = 0; i < size; i++) {
			if (obj.equals(elementData[i])) {
				return true;
			}
		}
		return false;
	}

	public int indexOf(Object obj) {
		for (int i = 0; i < size; i++) {
			if (obj.equals(elementData[i])) {
				return i;
			}
		}
		return -1;
	}

	public void add(Object index) {
		// 数组满了,扩容
		if (size == elementData.length) {
			// 船舰一个新的数组,长度旧数组长度的2 倍
			Object[] newArr = new Object[elementData.length * 2];
			// 将就数组的数据拷贝到新数组
			for (int i = 0; i < size; i++) {
				newArr[i] = elementData[i];
			}
			// 让elementData指向新数组
			elementData = Arrays.copyOf(elementData, elementData.length * 2);

		}
		// 给数组赋值
		elementData[size] = index;
		// 元素加一
		size++;
	}

	public void add(int index, Object obj) {
		if (index < 0 || index > size) {
			throw new MyArrayIndexOutOfBoundsException("数组索引越界异常" + index);
		}
		// 数组满了,扩容
		if (size == elementData.length) {
			// 船舰一个新的数组,长度旧数组长度的2 倍
			Object[] newArr = new Object[elementData.length * 2];
			// 将就数组的数据拷贝到新数组
			for (int i = 0; i < size; i++) {
				newArr[i] = elementData[i];
			}
			// 让elementData指向新数组
			elementData = Arrays.copyOf(elementData, elementData.length * 2);
		}
		// 后裔index及其后面的元素,从最后一个元素开始
		for (int j = size; j > index; j--) {
			elementData[j] = elementData[j - 1];
		}
		// 给数组第index位置赋值
		elementData[index] = obj;
		size++;

	}

	public Object remove(int index) {
		if (index < 0 || index > size) {
			throw new MyArrayIndexOutOfBoundsException("数组索引越界异常" + index);
		}

		return elementData[index];
	}

}
   测试类
import java.util.ArrayList;
import java.util.List;


public class TestLiner {
	public static void  main(String[] args) {
		List list=new ArrayList();
		
		list.add(111);
		list.add(222);
		list.add(333);
		list.add(444);
		list.add(555);
		
		list.add(3,123);
		
		list.remove(3);
		System.out.println(list.size());
		System.out.println(list.isEmpty());
		System.out.println(list.get(3));
		System.out.println(list.toString());
	}

}

单链表

线性表中每个节点有唯一的前驱和后继节点。
设计链式储存结构是,每个逻辑节点储存单独存储,为了表示逻辑关系,增加指针域。

  • 每个物理节点增加一个只想后继节点的指针域就是单链表
    (其接口信息与自定义异常与单链表相同。)
    单链表的结点 类
    
public class Node{
	/*private Object data;
	private Node next;*/
	Object data;
	 Node next;

	 public Node() {
			
		}
public Node(Object data) {
		super();
		this.data = data;
	}
	public Node(Object data, Node next) {
		super();
		this.data = data;
		this.next = next;
	}
	
	public Object getData() {
		return data;
	}
	public void setData(Object data) {
		this.data = data;
	}
	public Node getNext() {
		return getNext();
	}
	public void setNext(Node next) {
		this.data = next;
	}
	
	
}

 实现类
import java.util.List;



public class SingleLinkedList implements Liner {

	private Node head = new Node();// 头结点,不储存数据,
	private int size;// 一共有几个结点

	public int size() {

		return size;
	}

	public boolean isEmpty() {

		return size == 0;
	}

	public Object get(int i) {
		Node p = head;
		for (int j = 0; j <= i; j++) {
			p = p.next;
		}
		return p.data;
	}

	public boolean contains(Object obj) {
		if (isEmpty()) {
			return false;
		}
		for (int i = 0; i < size; i++) {
			Node p = head;
			if (obj.equals(p.data)) {
				return true;
			}
		}
		return false;
	}

	public int indexOf(Object obj) {
		for (int i = 0; i < size; i++) {
			Node p = head;
			if (obj.equals(p.data)) {
				return i;
			}
		}
		return -1;
	}

	public void add(Object index) {
		this.add(size, index);
	}

	public void add(int index, Object obj) {
		// 如果i位置错误异常
		if (index < 0 || index > size) {
			throw new MyArrayIndexOutOfBoundsException("数组指针越界异常" + index);
		}
		// 找到前 一个节点,从head节点开始
		Node p = head;
		for (int j = 0; j < index; j++) {
			p = p.next;
		}
		// 暂时创建一个节点
		Node newNode = new Node();
		newNode.data = obj;
		// 指明新结点的直接后继结点
		newNode.next = p.next;
		// 指明新结点的直接前驱节点
		p.next = newNode;
		size++;
	}
	//头结点删除
		public Object removeFirst(){
			
			Node temp = head;//移动指针
			if(temp == null){//头指针为空的情况
				System.out.println("这是一个空链表");
			}else{
				Node removeNode = temp;//头指针不为空,指向的结点即为第一个结点,也就是删除结点。定义这个变量是为存储删除的值
				temp = temp.next;//指针移动,指向删除结点的后一个结点
				head = temp;//把头指针指向删除结点的后一个结点
				size--;
				return removeNode.data;//把删除结点的值返回
			}
			return null;
		}
		
		//尾结点删除
		public Object removeLast(){
			Node temp = head;//定义一个临时指针,先指向头指针	
			if(temp == null){//头指针
				System.out.println("这是一个空链表");
			}else{
				Node currentNode = temp.next;//定义一个当前指针,把它作为移动指针。
				while(currentNode.next != null){//循环遍历指针
					temp = currentNode;//临时指针指向当前指针,即存储当前结点的值。
					currentNode = currentNode.next;//当前指针的移动
				}
				temp.next = null;//到了这里,说明当前currentNode.next==null的,即currentNode是没有后继结点了,而他就是要被删除的结点。把它前一个结点的指针域赋值为空,不指向它,那它不就删除了。
				size--;
				return currentNode.data;//把删除结点的值返回
			}
			return null;
		}
		
		//删除指定的序号的结点
		public Object remove(int index){
			Node temp = head;//定义临时指针
			if(temp == null){//头指针为空
				System.out.println("这是一个空链表");
			}else{
				Node currentNode = temp.next;//定义一个当前指针的变量
				int i = 1;//定义一个记录位置的变量
				if(index<1 || index>size+1){
					System.out.println("删除位置不合理");
				}
				while(currentNode.next!=null){
					if(index == i++){
						temp = currentNode;//把当前结点的值即要删除的结点存储到temp临时指针中。目的是要把它存储的值返回回来。
						currentNode = currentNode.next;
						size--;
						return temp.data;
					}
					currentNode = currentNode.next;
				}
			}
			
			return null;
			
		}



	/*public Object remove(int index) {
		if(index<1||index>size+1){
			throw new MyArrayIndexOutOfBoundsException("位置不合法");
			
		}
		return index;
	
	}
*/
	@Override
	public String toString() {
		if (size == 0) {
			return "[]";
		}
		StringBuilder builder = new StringBuilder("[");
		Node p = head;
		for (int i = 0; i < size; i++) {
			if (i != size - 1) {
				builder.append(p.data + ",");
			} else {
				builder.append(p.data);
			}
		}
		builder.append("]");
		return builder.toString();

	}
}


  测试类
import java.util.List;


public class TestSingleLinkedList {
	public static void  main(String[] args) {
		SingleLinkedList list= new SingleLinkedList();
		
		list.add(111);
		list.add(222);
		list.add(333);
		list.add(454);
		list.add(555);
		
		list.add(5,123);
		
		list.remove(3);
		System.out.println(list.size());
		System.out.println(list.isEmpty());
		System.out.println(list.get(2));
		System.out.println(list.toString());
	}

}

发布了43 篇原创文章 · 获赞 6 · 访问量 1539

猜你喜欢

转载自blog.csdn.net/weixin_43729631/article/details/102593584
今日推荐