因为数据结构有一点难度,有些lazy的同学不愿意去深究,学完了代码都没打几个,没错说的就是你肖兆菲同学,以下我将我打的电脑代码复制粘贴过来
首先先看链表
关于单链表:
1、概念
在单链表中由于数据元素的存储空间一般不是连续的,因此为了完善的表示单链表的逻辑结构,其中每一个数据元素必须由两部分构成:一部分是数据元素中的数据值,另一部分是数据元素的地址值。这两部分信息构成了单链表的一个节点。因此,在用单链表表示线性表时,每个结点的存储地址是任意的,即存储位置是无序的。
2、结构
对于单链表来说,每个节点的结构都是(data,next),节点中有两个部分:data域—存放结点值的数据域,next—存放结点的直接后续的地址的链域。
1.0
编写一个Node类来充当结点的模型。我们知道,其中有两个属性,1存放数据的data,2存放下一结点的引用,
public class Node<T> { //单链表结点类,T指定结点的元素类型
//1. 定义成员变量
public T data; //数据域,存储数据元素
public Node<T> next; //地址域,引用后继结点
//2. 定义构造方法
public Node(T data, Node<T> next) { //构造结点,data指定数据元素,next指定后继结点
this.data = data; //T对象引用赋值
this.next = next; //Node<T>对象引用赋值
}
public Node() {
this(null, null);
}
public String toString() { //返回结点数据域的描述字符串
return this.data.toString();
}
}
2.2、单链表的简单操作(增加,删除,获取总长度,链表元素排序,链表遍历)
我们依次来实现以下方法
1 判断是否为空
2 获取设置某元素
3 获取大小
4 插入某元素
5 移除某元素
6 清除该链表
7查询某元素
8 包含某元素
9 插入不同元素
Node.java
public Node{
public Node<T> head; //头指针,指向单链表的头结点
public SinglyList() { //构造方法,构造空单链表
this.head = new Node<T>(); //创建头结点,data和next值均为null
}
public SinglyList(T[] values) {
this(); //创建空单链表,只有头结点
Node<T> rear = this.head; //rear指向单链表最后一个结点
for (int i = 0; i < values.length; i++) { //若values.length==0,构造空链表
if (values[i] != null) {
rear.next = new Node<T>(values[i], null); //尾插入,创建结点链入rear结点之后
rear = rear.next; //rear指向新的链尾结点
}
}
}
List.java
public interface List<T> {
public boolean isEmpty(); //判断线性表是否为空,若空返回true
public int size(); //返回线性表元素个数(长度)
public T get(int i); //返回第i个元素
public void set(int i, T x); //设置第i个元素为x
public String toString(); //返回线性表所有元素的描述字符串
public int insert(int i, T x); //插入x作为第i个元素,x!=null
public int insert(T x); //在线性表最后插入x元素,返回x序号
public T remove(int i); //删除第i个元素,返回被删除元素
public void clear(); //删除线性表所有元素
public int search(T key); //查找首次出现的与key相等元素,返回元素序号i
public boolean contains(T key); //判断是否包含关键字为key元素
public int insertDifferent(T key); //插入不重复元素
public T remove(T key); //删除首次出现的与key相等元素,返回被删除元素
public boolean equals(Object obj); //比较两个线性表所有元素是否对应相等
//SeqList中有问题,暂时去掉此方法,2016.11.08
// public void addAll(List<T> list); //在this中添加list的所有元素,集合并运算
public void print(); // *** 输出线性表(可以借用toString()方法) ****
}
SeqList.java
顺序链表
public class SeqList<T> implements List<T>, Iterable<T> { // 10.2.1,实现可迭代接口{ protected Object[] element; // 对象数组,保护成员 protected int n; // 顺序表元素个数(长度) private final static int LENGTH = 64; // 顺序表默认容量为64 public SeqList() { // 创建默认容量的空表,构造方法重载 this(SeqList.LENGTH); // 调用本类已声明的指定参数列表的构造方法 } /** * 顺序表有参构造方法 * * @param length * 顺序表容量length */ public SeqList(int length) { // 构造容量为length的空表 // // 容错技术 length = length < 0 ? SeqList.LENGTH : length; // 假如length<0,则构造默认容量的空表 this.element = new Object[length]; // 申请数组的存储空间,元素为null。 // 若length<0,Java抛出负数组长度异常 java.lang.NegativeArraySizeException this.n = 0; } /** * 顺序表有参构造方法。 * * @param values * 存储元素数组 */ public SeqList(T[] values) { // 构造顺序表,由values数组提供元素,忽略其中空对象 this(values.length); // 创建容量为values.length的空表 for (int i = 0; i < values.length; i++) { // 复制数组元素,O(n) this.element[i] = values[i]; // 对象引用赋值 } this.n = values.length; // element.length; }以下实现SeqList方法
public boolean isEmpty() { // 判断顺序表是否空,若空返回true,O(1)
return this.n == 0;
}
public int size() { // 返回顺序表元素个数,O(1)
return this.n;
}
public T get(int i) { // 返回第i个元素,0≤i<n。若i越界,返回null。O(1)
if (i >= 0 && i < this.n)
return (T) this.element[i]; // 返回数组元素引用的对象,传递对象引用
// return this.element[i]; //编译错,Object对象不能返回T对象
return null;
}
public void set(int i, T x) {
if (x == null) {
throw new java.lang.NullPointerException("x==null"); // 抛出空对象异常
}
if (i >= 0 && i < this.n) {
this.element[i] = x;
} else {
throw new java.lang.IndexOutOfBoundsException(i + ""); // 抛出序号越界异常
}
}
public String toString() {
String str = this.getClass().getName() + "("; // 返回类名
if (this.n > 0)
str += this.element[0].toString(); // 执行T类的toString()方法,运行时多态
for (int i = 1; i < this.n; i++)
str += ", " + this.element[i].toString(); // 执行T类的toString()方法,运行时多态
return str + ") "; // 空表返回()
}
public int insert(int i, T x) {
if (x == null) {
throw new NullPointerException("x==null"); // 抛出空对象异常
}
// 以下两个语句用于容错处理
if (i < 0) {
i = 0; // 插入位置i容错,插入在最前
}
if (i > this.n) {
i = this.n; // 插入在最后
}
// 以下语句用于扩容
Object[] source = this.element; // 数组变量引用赋值,source也引用element数组
if (this.n == element.length) { // 若数组满,则扩充顺序表的数组容量
this.element = new Object[source.length * 2]; // 重新申请一个容量更大的数组
for (int j = 0; j < i; j++) { // 复制当前数组前i-1个元素
this.element[j] = source[j];
}
}
// 以下语句用于原有元素后移
for (int j = this.n - 1; j >= i; j--) { // 从i开始至表尾的元素向后移动,次序从后向前
this.element[j + 1] = source[j];
}
this.element[i] = x;
// /// 添加元素后n加1
this.n++;
return i;
}
/**
* 顺序表尾插入x元素,返回x序号。成员方法重载
*
* @param x
* 插入的元素
* @return 返回插入元素的索引位置
*/
public int insert(T x) { // 顺序表尾插入x元素,返回x序号。成员方法重载
return this.insert(this.n, x); // 插入操作中,this.n加1
}
我自己第一次写的SeqList版本
public class SeqList {
private int maxSize;
private int size;
private Object[] arrayList;
public SeqList(int sz){
maxSize=sz;
size=0;
arrayList=new Object[sz];
}
public void insert(int i,Object obj)throws Exception{//顺序表的 插入
if(size==maxSize)
throw new Exception("顺序表已满,无法插入!");
if(i<0||i>size)
throw new Exception("插入位置不存在!");
//for(int j=i;j<=size;j++)
// arrayList[j+1]=arrayList[j];这不是每个后移了,这是把后面的每个都变成arrayList[j]
for(int j=size;j>i;j--){//这个才能实现真正的后移~!!
arrayList[j]=arrayList[j-1];
}
arrayList[i]=obj;
size++;
}
public Object delete(int i)throws Exception{//顺序表 删除
if(size==0)
throw new Exception("顺序表已为空");
if(i<0||i>size)
throw new Exception("删除位置不存在!");
Object obj=arrayList[i];
for(int j=i;j<size;j++){
arrayList[j]=arrayList[j+1];//前移~
}
size--;
return obj;
}
public Object getData(int i)throws Exception{//取值
if(i<0||i>size)
throw new Exception("该位置不存在!");
return arrayList[i];
}
public int getSize(){//大小
return size;
}
public boolean isEmpty(){//是否为空
return size==0;
}
}
@SuppressWarnings("unchecked")
public T remove(int i) { // 删除第i个元素,0≤i<n,返回被删除元素。若i越界,返回null。//??若i越界,抛出序号越界异常
if (this.n > 0 && i >= 0 && i < this.n) {
T old = (T) this.element[i]; // old中存储被删除元素
for (int j = i; j < this.n - 1; j++) {
this.element[j] = this.element[j + 1]; // 元素前移一个位置
}
this.element[this.n - 1] = null; // 设置数组元素对象为空,释放原引用实例
this.n--;
return old; // 返回old局部变量引用的对象,传递对象引用
}
return null;
// throw new IndexOutOfBoundsException(i+""); //抛出序号越界异常
}
public void clear() {
this.n = 0; // 设置长度为0,未释放数组空间
// 释放数组空间
// for(int i = 0; i < this.size(); i++) {
// this.element[i] = null;
// }
}
public int search(T key) {
for (int i = 0; i < this.n; i++) {
if (key.equals(this.element[i])) // 执行T类的equals(Object)方法,运行时多态
return i;
}
return -1; // 空表或未找到时
}// 不能用逐元循环,无法返回i
public T remove(T key) { // 删除首个与key相等元素,返回被删除元素;查找不成功返回null
return this.remove(this.search(key)); // 先查找,再调用remove(i)。若查找不成功,返回-1,则不删除
}
以上是结合老师代码和我的作业发的程序,我依旧觉得不够简洁,下次会再发一个