数据元素:例如单向链表的一个节点 拥有 头指针和数据两个数据组成
四种存储方式 :
顺序表的实现 :
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;
}
}
}