`
费文—jmiss
  • 浏览: 34924 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

自定义链表

 
阅读更多

链表是非连续、无顺序的数据结构,链表中元素与元素之间的内存地址没有顺序关系。链表由一个个结点组成,结点中存储两类信息,第一类是存储入结点的数据,第二类是结点的指向。链表分为单项链表,双向链表,环形链表,单项链表中只有一个结点指向,指向的的下一个结点的内存地址,只能单向移动,单项操作;双向链表有两个结点指向,一个指向上一个结点的内存地址(父结点),另一个指向下一个结点的内存地址(子结点),可以双向运动,双向操作;环形链表其实是双向链表的首位结点相连。

对于链表,其好处是可以避免浪费内存空间,节省内存资源,不想数组定长会不可避免的浪费内存空间,不可以连续读取,连续操作,但是其大小可以动态改变。

 

/**
 * 双向列表结点类
 * @author lenovo
 *
 */

public class LinkNode {

	private Object obj;
	private LinkNode child;	//子类结点
	private LinkNode parent;//父类结点
	
	/**
	 * 创建有参的	构造方法
	 * @param obj
	 */
	public LinkNode(Object obj){
		this.obj=obj;
	}
	
	public LinkNode(){
		
	}

	public Object getObj() {
		return obj;
	}

	public void setObj(Object obj) {
		this.obj = obj;
	}

	public LinkNode getChild() {
		return child;
	}

	public void setChild(LinkNode child) {
		this.child = child;
	}

	public LinkNode getParent() {
		return parent;
	}

	public void setParent(LinkNode parent) {
		this.parent = parent;
	}
	
		
}

 

 

 

/**
 * 实现双向链表的方法类
 * 
 * @author lenovo
 * 
 */
public class LinkList {


	private static LinkNode head = null; // 头结点
	private LinkNode foot = head; // 尾结点

//	public static void main(String args[]) {
//
//		LinkList list = new LinkList();
//
//		list.add("新来的元素yes");
//
//		// 加入结点
//		for (int i = 0; i < 10; i++) {
//			list.add("链表元素" + i);
//		}
//
//		 list.set("XXX", 8);
//
//		 // 根据索引插入结点
//		// list.add("插入的", 8);
//		
//		 list.add("新来的元素");
//		 list.add("新来的元素2");
//
//		// 根据索引删除结点
//		 list.remove("新来的元素");
//
//		// 清空链表
//		 list.clear();
//
//		// 打印链表
//		list.printList(head);
//
//		// 得到链表的长度
//		int len = list.size();
//		System.out.println("长度:" + len);
//
//		 LinkNode temp = list.get(1); // 根据索引得到结点并打印
//		 list.printList(temp);
//
//	}

	/**
	 * 添加元素的方法
	 * 
	 * @param obj
	 *            :添加的元素
	 */
	public void add(Object obj) {

		LinkNode root = new LinkNode(obj);

		// 判断链表是否为空
		if (head == null) {
			head = root;
			foot = root;
		} else {
			foot.setChild(root);
			root.setParent(foot);

			// 为节点变为root
			foot = root;
		}

	}

	/**
	 * 插入元素的方法
	 * 
	 * @param obj
	 *            :插入的元素
	 * @param index
	 *            :要插入的索引
	 */
	public void add(Object obj, int index) {

		LinkNode root = new LinkNode(obj);

		if (index > size() || index < 0) {
			throw new RuntimeException("下标越界:" + index + ",size:" + size());

		} else {
			if (index == 0) { // 如果在第一个索引处插入
				head.setParent(root);
				root.setChild(head);

				head = root;

			} else if (index > 0 && index < size()) {
				int count = 0; // 计数器

				LinkNode n = head.getChild();
				while (index != count + 1) { // 得到想要插入处原来的结点
					n = n.getChild();
					count++;
				}

				LinkNode m = n.getParent();
				// 设置新的关系
				m.setChild(root);
				root.setParent(m);

				root.setChild(n);
				n.setParent(root);

			} else if (index == size()) { // 如果在结尾处插入
				add(obj);
			}
		}
	}

	/**
	 * 根据索引得到结点
	 * 
	 * @param index
	 *            :索引
	 * @return
	 */
	public LinkNode get(int index) {
		if (index > size() || index < 0) {
			throw new RuntimeException("下标越界:" + index + ",size:" + size());

		} else {
			int count = 0; // 定义计数器

			LinkNode root = head;

			while (count != index) { // 循环得到结点
				root = root.getChild();
				count++;

			}

			return root;
		}

	}

	/**
	 * 根据索引删除结点
	 * 
	 * @param index
	 */
	public void remove(int index) {

		if (index > size() || index < 0) {

			throw new RuntimeException("下标越界:" + index + ",size:" + size());
		} else {

			// 得到指定索引的结点
			LinkNode root = this.get(index);
			// 得到结点的父结点
			LinkNode proot = root.getParent();
			// 得到结点的子结点
			LinkNode croot = root.getChild();

			if (proot == null) { // 如果是第一索引的结点
				head = croot;
			} else if (croot == null) { // 如果是最后索引的结点
				proot.setChild(null);
			} else {
				proot.setChild(croot);
				croot.setParent(proot);
			}

		}

	}

	/**
	 * 根据元素删除结点
	 * 
	 * @param obj
	 */
	public void remove(Object obj) {

		LinkNode root;

		if (head == null) {
			throw new RuntimeException("链表为空");
		}

		if (head.getObj() == obj) { // 如果是头结点
			root = head.getChild();
			root.setParent(null);
			head = root;
			return;
		} else if (foot.getObj() == obj) { // 如果是尾结点
			root = foot.getParent();
			root.setChild(null);
			foot = root;
			return;
		} else {
			root = head.getChild();
			for (int i = 0; i < size(); i++) {
				if (root.getObj() == obj) {
					remove(i + 1); // 从1的索引开始遍历
					return;
				}

				root = root.getChild();
			}
		}

	}

	/**
	 * 替换链表上相应索引结点的方法
	 * 
	 * @param obj
	 * @param index
	 */
	public void set(Object obj, int index) {

		if (index < 0 || index > size()) {
			throw new RuntimeException("下标越界:" + index + ",size:" + size());
		}

		remove(index);
		add(obj, index);

	}

	/**
	 * 统计链表长度的方法
	 * 
	 * @return
	 */
	public int size() {

		LinkNode root = new LinkNode(); // 创建一个LinkNode对象,开辟内存空间
		root = head;

		// 定义一个计数器
		int count = 0;

		while (root != null) {

			count++;
			root = root.getChild();
		}
		return count;

	}

	/**
	 * 清空链表的方法
	 */
	public void clear() {

		head.setChild(null);
		foot.setParent(null);
		head = null;
		foot = head;
	}

	/**
	 * 遍历列表
	 * 
	 * @param root
	 */
	public void printList(LinkNode root) {

		if (root != null) {

			Object obj = root.getObj();

			System.out.println(obj);

			if (root.getChild() != null) {

				printList(root.getChild()); // 递归调用
			}
		}
	}

}
 
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics