《java常用算法手册》 第二章 数据结构 顺序表 单链表

数据元素:例如单向链表的一个节点  拥有 头指针和数据两个数据组成

四种存储方式 :

 

 

 

 

 

 

顺序表的实现 :

package LineStructure;

//顺序表
public class SeqList<T> extends Object {

	// 表长
	private int length;

	// 节点元素
	private Object[] element;

	// 空构造 默认容量的空表
	public SeqList() {
		this(64);
	}

	// 初始化 构造容量为length的空表
	public SeqList(int length) {
		this.length = 0;
		this.element = new Object[length];
	}

	// 构造有元素的顺序表
	public SeqList(T ele[]) {
		this(ele.length);
		// 复制元素到顺序表中
		for (int i = 0; i < ele.length; i++) {
			element[i] = ele[i];
		}
	}

	// 判断是否为空表
	public boolean isEmpty() {
		return this.length == 0;
	}

	// 返回 长度
	public int size() {
		return this.length;
	}

	// 返回顺序表所有元素的描述字符串,形式为“(,)” 覆盖toString方法
	public String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append("{");
		sb.append(this.element[0]);
		for (int i = 1; i < this.length; i++) {
			sb.append(","+this.element[i]);
		}
		
		sb.append("}");
		return sb.toString();
	}

	// 查找节点 返回第i个元素
	public T get(int i) {
		if (i > 0 && i < this.length) {
			return (T) this.element[i];
		} else {
			return null;
		}
	}

	// 修改第i个元素 注意并不是插入元素
	public void set(int i, T value) {
		if (value == null) {
			throw new NullPointerException("sorry x == null");
		} else if (i > 0 && i < this.length) {
			this.element[i] = value;
		} else {
			throw new java.lang.IndexOutOfBoundsException("Sorry your element :" + i + " IndexOutOfBounds");
		}
	}

	// 插入元素
	public String insert(int i, T value) {
		if (value == null) {
			throw new NullPointerException("x == null");
		} else if (i < 0) {// 插入到最前端
			i = 0;
			// this.element[0] = value;
		} else if (i > this.length) {// 插入到最后端
			i = this.length;
			// this.element[this.length] = value;
		}

		// 由于无法直接扩容 element2临时存放值钱的元素
		Object[] elementTemp = this.element;
		
		// 扩容 重新开辟空间存放元素
		if (i > this.length) {
			this.element = new Object[elementTemp.length * (2 / 3)];
		}
		// 赋值插入位置之前的元素
		// 前i-1个元素给新的element
		for (int j = 0; j < i; j++) {
			this.element[j] = elementTemp[j];
		}
		// 移动插入位置之后的元素
		// 插入到中间 i之后的元素后移 顺序为从前向后,也可以从后向前 
		//错误 只能从后向前 elementTemp是this.element的引用 不是副本
		/*for (int j = i; j < elementTemp.length-1; j++) {
			this.element[j + 1] = elementTemp[j];
		}*/
		//从后向前
		for(int j=this.length-1;j>=i;j--){
			this.element[j+1] = elementTemp[j] ;
		}
		
		// 插入元素
		this.element[i] = value;
		this.length++;
		return "insert success element" + value + "insert into position: " + i;
	}

	// 默认插入 插入到表最后
	public String insert(T value) {
		return insert(this.length, value);
	}

	// 移除元素
	public String remove(int i) {
		if (i >= 0 && i < this.length && this.length > 0) {
			// i之后元素向前移动
			for (int j = i; j < this.length - 1; j++) {
				this.element[j] = this.element[j + 1];
			}
			// 注意:最后一个元素设置为空
			this.element[this.length - 1] = null;
			this.length--;
		} else {
			return null;
		}
		return "success";
	}

	// 清除
	public void clear() {
		for (int j = 0; j < this.length; j++) {
			this.element[j] = null;
		}
		this.length = 0;
	}

	// 查找元素 返回序号
	public int search(T value) {
		for (int i = 0; i < this.length; i++) {
			if (value == this.element[i]) {
				return i;
			}
		}
		return -1;
	}

	public boolean contains(T value) {
		return this.search(value) != -1;
	}

}

 

 

单链表实现 :

package LineStructure;

public class LinkedList<T> extends Object {

	// 理解java引用 http://zwmf.iteye.com/blog/1738574

	// 两种思路 第一种插入节点(包含数据)
	// 参考 https://www.cnblogs.com/whgk/p/6589920.html
	// 第二种插入数据,需要new 节点,感知不到节点的存在
	// https://blog.csdn.net/jianyuerensheng/article/details/51200274

	// 每一个节点存放下一个节点的引用
	public class Node {
		private Object data;
		// 存放下一个节点的引用
		private Node next;

		// Node的构造
		public Node() {
			data = null;
		}

		// Node的构造
		public Node(T data) {
			this.data = data;
		}
	}

	// 头节点 的Data 一般是不储存数据的
	private Node head; // 头引用(指针)
	private Node rear; // 尾引用(指针)
	private Node point; // 临时引用(指针)
	private int length; // 链表长度

	// 链表类的构造方法,只构造出不含数据的头结点。 此时尾引用指向头引用 构成一个完整的链表
	// 头节点 的Data 一般是不储存数据的
	public LinkedList() {
		head = new Node();
		rear = head;
		length = 0;
	}

	// 增加节点
	public void addNode(Node node) {
		// 链表中已有节点 需要遍历到最后一个节点
		Node temp = head; // 一个移动的指针(遍历指针)(从头节点开始遍历)
		// 如果链表是空的则 temp为head,head之后追加Node
		while (temp.next != null) { // 遍历单链表,直到遍历到最后一个则跳出循环。
			temp = temp.next; // 遍历指针往后移一个结点,指向下一个结点。
		}
		temp.next = node; // temp为最后一个结点或者是头结点,将其next指向新结点 这样头节点中没有数据
	}

	// 插入指定位置
	// 前一个结点 当前位置 后一个结点
	// temp temp.next temp.next.next
	public void insertNodeByIndex(int index, Node node) {
		int position = 1;
		Node temp = head;
		while (temp.next != null) {
			if (index == position) {
				// 插入节点指向之前temp的next
				node.next = temp.next;
				// temp的next指向node
				temp.next = node;
				return;// 注意return 减少时间复杂度
			}
			position++;
			temp = temp.next;// 指针后移 对temp的赋值不会影响整个链表
		}
	}

	// 删除节点
	public void delNodeByIndex(int index) {
		int position = 1;
		Node temp = head;// 指针 当前节点

		// 之前写法 错误: while条件有误 temp.next 可能为空
		/*
		 * while (temp.next != null) { if (index == position) { temp.next =
		 * temp.next.next; // 对temp的赋值不会影响整个链表(temp为临时指针) 但是对temp.next赋值影响了链表的指针
		 * return;// 注意return 减少时间复杂度 } position++; temp = temp.next; //
		 * 对temp的赋值不会影响整个链表(temp为临时指针) 但是对temp.next赋值影响了链表的指针
		 * 
		 * }
		 */
		// 修改while条件
		while (index != position) {
			position++;
			temp = temp.next; // 对temp的赋值不会影响整个链表(temp为临时指针) 但是对temp.next赋值影响了链表的指针
		}
		temp.next = temp.next.next; // 对temp的赋值不会影响整个链表(temp为临时指针) 但是对temp.next赋值影响了链表的指针
		return;// 注意return 减少时间复杂度

	}

	// 计算长度
	public int getLength() {
		int position = 0;
		Node temp = head;// 指针 当前节点
		while (temp.next != null) {
			position++;
		}
		temp = temp.next;
		return position;
	}

	// 按下标查找节点
	// 头节点 的Data 一般是不储存数据的
	public T find(int position) {
		// 0为头节点 没有数据
		int start = 0;
		Node temp = head;
		while (position != start) {
			temp = temp.next;
			start++;
		}
		return (T) temp.data;

	}

	// 查找元素的值,返回下标
	// 头节点 的Data 一般是不储存数据的
	public int search(T value) {
		int start = 1;
		Node temp = head;

		// 之前的写法 错误 while条件错误 尾节点的temp.next可能为空!!
		/*
		 * while(temp.next != null) { if(temp.next.data == value) { return start; }
		 * start++; temp = temp.next;
		 * 
		 * }
		 */
		while (temp.next.data != value) {
			start++;
			temp = temp.next;
		}
		return start;

	}

	// 遍历单链表,打印所有data
	// 头节点 的Data 一般是不储存数据的
	public String toString() {
		Node temp = head;
		StringBuffer sb = new StringBuffer();
		sb.append("headNode");
		while (temp.next != null) {
			sb.append("," + temp.next.data);
			temp = temp.next;
		}
		return sb.toString();
	}

	// 链表sort
	// 关于sort:https://www.cnblogs.com/whgk/p/6596787.html
	public void selectSort() {
		Node temp = head;// 外层指针
		while (temp.next != null) {
			Node temp2 = temp;// 内层指针
			while (temp2.next != null) {
				if ((int) temp.next.data > (int) temp2.next.data) {
					int tempData = (int) temp.next.data;
					temp.next.data = temp2.next.data;
					temp2.next.data = tempData;
				}
				temp2 = temp2.next;
			}
			temp = temp.next;
		}
	}

}

猜你喜欢

转载自blog.csdn.net/weixin_41395565/article/details/83063763