数据结构3(双向链表)

 

package doubleLinkedList;

public class LinkedList {
	/**数据存储*/
	private int data;
	/**指向前一个节点的引用*/
	private LinkedList prior;
	/**指向后一个节点的引用*/
	private LinkedList next;
	
	public int getData() {
		return data;
	}
	public void setData(int data) {
		this.data = data;
	}
	public LinkedList getPrior() {
		return prior;
	}
	public void setPrior(LinkedList prior) {
		this.prior = prior;
	}
	public LinkedList getNext() {
		return next;
	}
	public void setNext(LinkedList next) {
		this.next = next;
	}
	
	
	
}

package doubleLinkedList;

import java.util.Scanner;
/**
 * 双向链表比前面的顺序表还是单向链表都要有难度,但是只要想明白她的过程即可
 * 画图更容易看明白
 * 这里就不可用重写toString的方法去查看对象的情况了,它会循环导致堆栈溢出
 * @author 后飞IT
 *
 */
public class LinkedListTest {
	public static void main(String[] args) {
		LinkedListTest llt = new LinkedListTest();
		LinkedList ll = llt.init();
		
		// 获取双向链表的长度
		// System.out.println(llt.getLength(ll));
		
		
		// 插入数据
		// ll = llt.insertElem(ll, 1);
		
		// 找到数据
		// int position = llt.findByElem(2, ll);
		// System.out.println("要查找的数据的位置是:"+position);
		
		// 删除操作
		ll = llt.deleteElem(ll,3);
		
		
		// 显示双向链表的结构内容
		llt.showLinedList(ll);
	}

	/**
	 * 创建双向链表  (这里同样采用的也是倒序插入)
	 *      双向链表的初始化还是有那么麻烦的
	 * @return
	 */
	private LinkedList init() {
		Scanner sc = new Scanner(System.in);
		//首先在外边新建一个节点
		LinkedList temp = new LinkedList();
		System.out.println("请输入当前节点的数据");
		//设置data字段
		temp.setData(sc.nextInt());
		//还没有其他节点,此时为null
		temp.setNext(null);
		temp.setPrior(null);
		//循环创建其他的节点
		for (int i = 0; i < 3; i++) {
			System.out.println("请输入当前节点的数据");
			LinkedList ll = new LinkedList();
			ll.setData(sc.nextInt());
			//将上一个创建的的引用放置到它的下一个引用
			ll.setNext(temp);
			//然而上个创建的节点的前一个引用则是当前创建的引用
			temp.setPrior(ll);
			//将此次创建的节点,赋值到temp上,以继续循环
			temp = ll;
		}
		//循环到最后的时候,temp保存的恰好是最开始的节点的那个引用,返回这个引用即可
		return temp;
	}

	/**
	 * 根据所有下标删除节点       	
	 * @param ll
	 * @param desc   begin with 0
	 * @return
	 */
	private LinkedList deleteElem(LinkedList ll, int desc) {
		LinkedList temp = ll;
		//获取当前的双向链表的长度
		int length = this.getLength(ll);
		// 先判断输入的位置是否合法
		if (desc < 0 || desc > length) {
			throw new RuntimeException("删除位置不对了");
		}
		// 删除的是第一个的时候      注意点:不管是删除添加之类的,应该分为三个特殊的部分     开头   结尾      中间      需要仔细验证
		if (desc == 0) {
			//将链表的第二个节点(index=1)的那个节点的前引用设为null,然后直接返回即可
			temp = temp.getNext();
			temp.getNext().setPrior(null);
			return temp;
		}
		// 先找到要插入的位置的前一个位置      ->   这个是有前后的指针的,所以直接找到那个位置也可以(这个里面做了多次的查询,要封装的,但是算了)
		int i = -1;
		while (true) {
			i++;
			if (temp != null) {
				if (i == desc - 1) {
					//此时中断循环,temp中保存的即是该删除位置的前一个节点
					break;
				}
				temp = temp.getNext();
			}
		}
		// 删除的是最后一个的时候(删除节点的下一个引用为null时,表示最后一个节点)
		if (temp.getNext().getNext() == null) {
			//把要删除的那个节点放空
			temp.setNext(null);
			System.out.println(ll + "\t " + temp);
			return ll;
		} else {
			// 把要删除那个位置的后面节点的前引用设置为要删除的那个节点的前节点
			temp.getNext().getNext().setPrior(temp);
			//要删除位置的前面一个节点的后节点设置为要删除的那个节点的后节点
			temp.setNext(temp.getNext().getNext());
			return ll;
		}

	}

	/**
	 * 获取当前链表的长度
	 * @param ll
	 * @return
	 */
	private int getLength(LinkedList ll) {
		LinkedList temp = null;
		temp = ll;
		int i = 0;
		while (true) {
			if (temp != null) {
				i++;
				temp = temp.getNext();
			} else {
				return i;
			}
		}
	}

	/**
	 * 插入元素
	 * 
	 * @param ll
	 * @param desc
	 *            插入的位置 begin with 0
	 * @return
	 */
	private LinkedList insertElem(LinkedList ll, int desc) {
		// 赋给一个中间值
		LinkedList temp = ll;
		Scanner sc = new Scanner(System.in);
		int length = this.getLength(ll);
		// 先判断输入的位置是否合法
		if (desc < 0 || desc > length) {
			throw new RuntimeException("插入位置不对了");
		}
		// 插入的位置刚好是第1个时,直接把新产生的节点放置在最前面,设置后前后的引用,然后直接返回即可
		if (desc == 0) {
			LinkedList newList = new LinkedList();
			System.out.println("输入当前节点的dat字段");
			newList.setData(sc.nextInt());
			newList.setPrior(null);
			newList.setNext(temp);
			temp.setPrior(newList);
			return newList;
		}
		// 先找到要插入的位置的前一个位置
		int i = -1;
		while (true) {
			i++;
			if (temp != null) {
				if (i == desc - 1) {
					break;
				}
				temp = temp.getNext();
			}
		}
		// 此时获得的temp恰好就是前一个节点
		LinkedList newList = new LinkedList();
		System.out.println("输入当前节点的dat字段");
		newList.setData(sc.nextInt());
		newList.setNext(temp.getNext());
		newList.setPrior(temp);
		temp.setNext(newList);
		return ll;
	}

	/**
	 * 将链表中的信息,如前后节点,输出~~
	 * 
	 * @param ll
	 */
	private void showLinedList(LinkedList ll) {
		LinkedList temp = null;
		temp = ll;
		while (true) {
			if (temp != null) {
				System.out.print("[");
				if (temp.getPrior() == null) {
					System.out.print("NULL\t");
				} else {
					System.out.print(temp.getPrior().getData() + "\t");
				}
				System.out.print(temp.getData() + "\t");
				if (temp.getNext() == null) {
					System.out.print("NULL\t");
				} else {
					System.out.print(temp.getNext().getData() + "\t");
				}
				System.out.print("]\n");
				temp = temp.getNext();
			} else {
				break;
			}
		}
	}

	/**
	 * 查询相应的元素的索引
	 * 
	 * @param arg
	 * @param ll
	 * @return
	 */
	private int findByElem(int arg, LinkedList ll) {
		LinkedList temp = ll;
		int position = -1;
		while (true) {
			if (temp != null) {
				position++;
				if (temp.getData() == arg) {
					return position;
				}
				temp = temp.getNext();
			} else {
				position = -1;
				return position;
			}
		}

	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值