单链表的插入,查找,删除

链表是一种重要的数据结构,相比于数组,数组更像是一个顺序表,数组只要第一个元素固定,那么在他后面的元素的地址一定固定,数组在内存中是一块连续的存储区域,我们可以根据下标找到他的每个元素,这是数组和链表的一个区别

链表,见名思意,一个链子连接起来的表,元素之间的联系靠的是这个链子,这也决定了链表中的每个元素不是连续的,第一个元素在内存中的一个地方,而下一个元素可以在离他很远的地方,他们之间有一个链子连接着,这个链子准确来说是指针,第一个元素指向第二个,依次指向下去,我们对某个元素进行操作的时候,我们只能从头依次查找找到这个元素再进行操作。单链表是指单向的链表,我们只能从他的头向后查找,而双向链表,不光可以从头部向后查找,也可以从后向前查找。

数组的查找,更改方便,而数组的增加,删除方便。数组可以根据下标找到元素,而链表只能从头部依次向后查找,相比于数组的增加,删除操作会涉及到元素的移动,链表就方便很多,我们只需要把他前后的指向的元素改变一下,就可以实现元素的增加和删除。

对链表的操作也是很基本的操作,下面只是对单链表的操作

定义一个节点类,定义他的数据域,和next指针(不能说是一个指针,他是下一个元素,指针更好理解)

package demo_linkedlist;

public class Node {
	public int element;
//	public Node pre;
	public Node next;
	public Node(){
		
	}
//	public Node(int element,Node pre,Node next){
//		this.element=element;
//		this.pre=pre;
//		this.next=next;
//	}
	public Node(int element,Node next){
		this.element=element;
		this.next=next;
	}
	@Override
	public String toString() {
		return element + "->"+next;
	}
	
	

}

在定义节点的时候,定义了一个head头节点,头节点始终指向链表中的第一个元素。这样对链表中的第一个数据进行操作的时候,可以方便些


一个节点的初始化方法,为什么倒过来定义,因为在定义指向下一个元素的next指针的时候是先定义前一个元素的next指向,然而后一个节点还没有定义,倒过来就解决了。

        private Node n10 = null;
	private Node n8 = null;
	private Node n7 = null;
	private Node n6 = null;
	private Node n5 = null;
	private Node n4 = null;
	private Node n3 = null;
	private Node n2 = null;
	private Node n1 = null;
	private Node head = null;

	public void init() {
		n10 = new Node(10, null);
		n8 = new Node(8, n10);
		n7 = new Node(7, n8);
		n6 = new Node(6, n7);
		n5 = new Node(5, n6);
		n4 = new Node(4, n5);
		n3 = new Node(3, n4);
		n2 = new Node(2, n3);
		n1 = new Node(1, n2);
		head = new Node(0, n1);
	}

遍历节点方法

/**
	 * 打印每个节点的值
	 */
	public void print() {
		Node star = head;
		while (star != null) {
			System.out.print(star.element + " ");
			star = star.next;
		}
		System.out.println();
	}

查找结点值为a的某个节点

/**
	 * 查找结点的值
	 */
	public Node find(int a) {
		Node current = n1;
		while (current.element != a) {
			if (current.next == null) {
				return null;
			}
			current = current.next;
		}
		return current;
	}

插入节点,这时候头节点head的作用就用上了,当插入节点值小于链表中的任何元素的时候,为了保证链表的有序,只需要改变头节点的指向就可以

/**
	 * 插入一个节点,并保证链表依然有序
	 */
	public Node insert(int a) {
		Node n9 = new Node(a, null);
		Node current = head;
		while (current.next != null) {
			if (a < current.element) {
				n9.next = current;
				current.next = n9;
				break;
			}
			if (current.element <= a && current.next.element > a) {
				n9.next = current.next;
				current.next = n9;
				break;
			}
			current = current.next;
		}
		if (current.element < a && current.next == null) {
			n9.next = null;
			current.next = n9;
		}
		return current;
	}

删除某个节点的方法,由于单链表的特点,我们只能从前向后查找,这样当我们找到要删除的节点的时候,由于前一个节点已经过去了,所以我们只能获得后一个节点,改变不了前一个节点的指向,解决的办法就是只需要定义两个节点,一个指向前一个,另一个指向后一个,每次遍历的时候这两个节点依次向后移动,当找到要操作的节点的时候,由于我们已经记录了前一个节点,这样只需要见到的改变一下指向即可。

/**
	 * 删除值为a的节点
	 */
	public Node delete(int a) {
		Node current = head;
		Node current1 = head.next;
		while (current1.next != null) {
			if (current1.element == a) {
				current.next = current1.next;
				return current;
			}
			current = current.next;
			current1 = current1.next;
		}
		if (current1.next == null) {
			current.next = null;
		}
		return current;
	}

完整代码:

package demo_linkedlist;

/**
 * 在链表中定义了一个head头节点,时钟在链表的头部,在执行插入操作的时候会方便些
 * 
 */

public class LinkedLists {
	private Node n10 = null;
	private Node n8 = null;
	private Node n7 = null;
	private Node n6 = null;
	private Node n5 = null;
	private Node n4 = null;
	private Node n3 = null;
	private Node n2 = null;
	private Node n1 = null;
	private Node head = null;

	public void init() {
		n10 = new Node(10, null);
		n8 = new Node(8, n10);
		n7 = new Node(7, n8);
		n6 = new Node(6, n7);
		n5 = new Node(5, n6);
		n4 = new Node(4, n5);
		n3 = new Node(3, n4);
		n2 = new Node(2, n3);
		n1 = new Node(1, n2);
		head = new Node(0, n1);
	}

	public static void main(String[] args) {
		LinkedLists l = new LinkedLists();
		l.init();
		l.print();// 遍历链表
		System.out.println("查找:" + l.find(6));
		l.insert(11);
		System.out.println("插入数据后:" + l.head);
		l.delete(11);
		System.out.println("删除后:" + l.head);
	}

	/**
	 * 打印每个节点的值
	 */
	public void print() {
		Node star = head;
		while (star != null) {
			System.out.print(star.element + " ");
			star = star.next;
		}
		System.out.println();
	}

	/**
	 * 查找结点的值
	 */
	public Node find(int a) {
		Node current = n1;
		while (current.element != a) {
			if (current.next == null) {
				return null;
			}
			current = current.next;
		}
		return current;
	}

	/**
	 * 插入一个节点,并保证链表依然有序
	 */
	public Node insert(int a) {
		Node n9 = new Node(a, null);
		Node current = head;
		while (current.next != null) {
			if (a < current.element) {
				n9.next = current;
				current.next = n9;
				break;
			}
			if (current.element <= a && current.next.element > a) {
				n9.next = current.next;
				current.next = n9;
				break;
			}
			current = current.next;
		}
		if (current.element < a && current.next == null) {
			n9.next = null;
			current.next = n9;
		}
		return current;
	}

	/**
	 * 删除值为a的节点
	 */
	public Node delete(int a) {
		Node current = head;
		Node current1 = head.next;
		while (current1.next != null) {
			if (current1.element == a) {
				current.next = current1.next;
				return current;
			}
			current = current.next;
			current1 = current1.next;
		}
		if (current1.next == null) {
			current.next = null;
		}
		return current;
	}

}

如有不对的地方欢迎指正!

posted @ 2017-11-10 21:29  In_new  阅读(1299)  评论(0编辑  收藏  举报