Java入门——自己写的LinkedList的增删查改方法

昨天写了简单的自己的ArrayList类,今天写写LinkedList类。(因为懒惰,原理就不写了)

使用一个自己写的结点类(包含了数据域和引用域)来实现相关操作。

 

构造MyLinkedList类

先写结点类:

package MyLinkedList;

public class Node {
	private Object data; //数据域
	private Node next; //引用,指向下一个结点
	
	//构造方法
	public Node() {
		// TODO Auto-generated constructor stub
		
	}
	//构造方法:传入数据,置空next
	public Node(Object data) {
		this.data = data;
		this.next = null;
	}

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

然后就可以构造链表类了

package MyLinkedList;

public class MyLinkedList {
	private Node head; // 头结点
	private Node last; // 尾结点
	private int size; // 结点长度

	/**
	 * 构造方法:初始化头结点和尾结点
	 */
	MyLinkedList() {
		head = new Node();
		last = head; // 初始状态头结点与尾结点指向同一个结点
	}

	
}

重写一个toString()方法

/**
	 * 规范链表输出格式
	 */
	public String toString() {
		StringBuffer sb = new StringBuffer();
		Node current = head; // 从头结点开始遍历
		while (true) {
			if (current.getNext() != null) {// 不是最后一个结点时(next域不为空)
				current = current.getNext(); // 先指向下一个结点(因为头结点的数据为空)
				sb.append(current.getData()); // 取出数据
				// 添加分隔符号
				sb.append("->");
			} else {
				// 遍历完了之后,退出循环
				break;
			}
		}
		// 去除最后一个分隔符
		sb.deleteCharAt(sb.length() - 1);
		sb.deleteCharAt(sb.length() - 1);
		return sb.toString();
	}

 

添加操作add()

我重载了两个添加操作的方法,一个是直接添加数据到链表尾部;另一个是在保证不越界的情况下,可以往链表的中间位置插入结点。

第一个添加操作:

/**
	 * 增加操作
	 * 
	 * @param obj 要添加的结点数据
	 */
	public void add(Object obj) {
		// 先创建一个结点
		Node node = new Node(obj);
		// 把新建的结点加入到链表中
		last.setNext(node);
		// 更改last的指向
		last = node;
		// 更改结点长度
		size++;
	}

查看效果:

package MyLinkedList;

public class TestMyLinkedList {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		//创建链表
		MyLinkedList myInt =new MyLinkedList();
		myInt.add(1);
		myInt.add(2);
		myInt.add(3);
		myInt.add("a");
		System.out.println(myInt.toString());
		
	}

}

注:因为类中数据类型为Object,可以为任何类型的数据,且一个链表中数据类型可以多样。

若想要链表数据类型任意但是统一,可以使用泛型。

第二种添加操作(插入)

/**
	 * 插入操作
	 * 
	 * @param desIndex 插入的目标位置下标
	 * @param obj      插入的结点数据
	 */
	public void add(int desIndex, Object obj) {
		// 判断下标是否合法
		if (desIndex < 0 || desIndex > size+1) { //(+1是因为,允许插入到尾部)
			try {
				throw new Exception("下标越界");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} else {
			// 其他地方可以正常插入,先创建一个结点
			Node node = new Node(obj);
			// 插入到头结点后一个位置
			if (desIndex == 0) {
				// 先把新结点的next指向原本头结点指向的位置
				node.setNext(head.getNext());
				// 使头结点的next指向新建立的结点
				head.setNext(node);
				// size增加
				size++;
			}
			// 其他位置
			else {
				// 首先需要从头遍历找到要插入位置的前一个结点
				Node before = head;
				for (int i = 0; i < desIndex; i++) {
					before = before.getNext();
				}
				// 循环结束,找到了before的位置
				// 先把新建的结点的next指向before的next结点
				node.setNext(before.getNext());
				// 将before的next指向新创建的结点
				before.setNext(node);

				// 若创建的结点是最后一个,需要重新设置last
				if (desIndex == size) {
					last = node;
				}
			}
		}

	}

效果查看:

异常测试:

 

删除操作remove()

删除操作重载了两个,一个是根据下标进行删除,一个是传入值,找到该值进行删除

根据下标删除:

/**
	 * 删除操作
	 * 
	 * @param desIndex 需要删除的结点位置
	 */
	public void remove(int desIndex) {
		// 判断位置下标是否合法
		if (desIndex < 0 || desIndex > size) {
			try {
				throw new Exception("下标越界");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		else {
			Node before = head; // 需要删除的前一个结点
			// 先找到before结点的位置
			for (int i = 0; i < desIndex; i++) {
				before = before.getNext();
			}
			// 循环结束,找到了before的位置
			// 将before的next指向要删除的下一个
			before.setNext(before.getNext().getNext());
			// 将要删除的结点的next置空
			// before.getNext().setNext(null);
			// size减少
			size--;

			// 若删除的是最后一个结点,需要更改last
			if (desIndex == size) {
				last = before.getNext();
			}
		}
	}

效果查看:

第二种,根据值查找删除(其中使用到的search查找方法是自己写的,在下一个部分)

/**
	 * 删除操作
	 * @param obj 需要删除的结点数据
	 */
	public void remove(Object obj) {
		// 获得要删除的元素位置下标
		int index = search(obj);
		if (index != -1) {
			// 直接调用前面的方法
			remove(index);
		} else {
			System.out.println("没有找到你要删除的元素");
		}
	}

效果查看:

myInt.remove((Integer)3); 

异常测试:

 

查找操作search()

在链表中查找某数据,返回位置下标。若没有找到,返回-1

/**
	 * 查找操作
	 * 
	 * @param obj 需要查找的结点数据
	 * @return 返回结点位置下标。若没有找到,返回-1
	 */
	public int search(Object obj) {
		int index = -1; // 记录下标
		Node node = head;
		// 遍历链表进行查找
		for (int i = 0; i < size; i++) {
			node = node.getNext();
			// 判断
			if (node.getData() == obj) {
				index = i;
				break; // 退出循环
			}
		}
		return index;
	}

效果:

System.out.println(myInt.search(3));

 

修改操作set()

修改也重载了两个。一个根据下标修改,一个根据原始值查找修改。

根据下标修改:

/**
	 * 更改操作
	 * @param desIndex 需要更改的结点位置下标
	 * @param obj 需要更改的结点新数据
	 */
	public void set(int desIndex, Object obj) {
		// 判断位置下标是否合法
		if (desIndex < 0 || desIndex > size) {
			try {
				throw new Exception("下标越界");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		else {
			Node node=head; //获得要删除的结点
			//遍历获得
			for(int i=0;i<=desIndex;i++) {
				node=node.getNext();
			}
			//更改数据
			node.setData(obj);
		}
		
	}
	

效果:

根据值查找修改:

 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值