`
greemranqq
  • 浏览: 966123 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论

数据结构--简单链表

阅读更多

一、序言

       数据结构在大学都学过,由于大学认识不够,对这个有点酱油了,很多东西都是知道其概念,当然基本的应用也会,但是偶尔的面试等一些地方的应用,还是不够,这里再复习一些知识,给大家分享,知识来源于数据结构的书和网上的东西。

 

二、抽象数据类型

       ADT(abstract data type)是带有一组操作的的的一些对象的集合。对于集合的ADT,我的理解是:拥有对数据的存放结构的定义(比如Node、List),是一种自定义的数据结构,同时含有对这些元素进行操作的描述(比如:add、remove、insert),这些都是没有具体实现,但是可以通过这些定义和描述我们可以进行分析和研究,同时给实现留下空间,JAVA 集合里面对这块做了多种实现。

 

三、简单链表

       简单链表包含了存储元素和指向下一个元素的“指针”,这里我们仅通过图进行简单描述:

       

 

     可以看出,上面有一个头节点,通过next 连接和后续节点,最后一个节点指向null.我们可以创建自己的单链表:

     

// 我们先定义一个简单的节点形式的结构
public  class Node<T> {
	T element;
	Node<T> next;
}

    

// 通过节点,可以实现简单链表
public class LinkNode<T> extends Node<T>{
	// 头结点
	private Node<T> head = null;
	public LinkNode(){head = new Node<T>();}
	
	// 基本方法
	void add(Node<T> node){}
	// 移除
	void remove(Node<T> node){}
	// 指定位置添加
	void insert(Node<T> node,int index){}
	// 查找
	Node<T> find(T t){return null;}
}

 

四、操作分析:

       1.add () 一个节点:下图可以看出我们默认添加到头节点,讲原来head 结点的执行改变,同时将新节点的next 指向下个节点就行了。当然我们也可以放在末尾,原理类似。

       
        
 
      2.remove() 移除:假设我要移除第二个节点,那么仅仅需要将第一个节点的next 指向第三个就行了。


  

 

    3.find(Node node) 查找:链表的查找会从头开始遍历,和每一个元素进行匹配,循环依次next,显然这个是线性查找,效率没数组那么快,当然在设计过程中,我们可以通过插入时排序,数组存放元素灯方式节省时间,当然会浪费一部分插入的时间,或者存储空间。

     

 
 

     4.insert(Node node,int index) 指定位置插入,这个就不贴图了,可以在next 移动的时候记录下标,在下标为index 的位置插入就行了。

 

五、单向链表反转:这里的反转分为有头结点和没有头节点的情况,但是原理都差不多,这里为了上图理       解,我们用有头节点的情况。

    1.先判断头节点的next 是否存在元素节点,如果存在元素的情况下,还得判断第一个元素的next 是否还有节点,如果没有,表示只有一个节点,直接就返回了,没必要反转。

    2.在有头节点的情况,原理差不多,我们先把头结点隔离开,然后把第一个节点断开,并且指向null,为了能继续找到下面的节点,我们需要一个临时变量,将后面的节点连接起来,现在的图为:

     
    
       
 
      3.然后我们将cur 指向下一个节点C,节点B 的next 指向A(first),同时移动之后将B作为first节点,等待下一次连接,如图:

       
      
 

      

    4.反复执行该操作,直到最后一个节点(C)指向B,这时候cur = null,first = C节点,最后将头节点head 指向 first 节点就行了。

      

Node<T> reverse(Node<T> node){
		Node<T> first;
		Node<T> cur;
		// 判断是否有下一个节点(A),临时节点保存(B后续节点)
		if((first = node.next) == null || (cur = first.next) == null){
			return node;
		}
		// 头节点断开
		node.next = null;
		// 断开第一个有效节点(A)
		first.next = null;
		while(cur != null){
			Node<T> temp = cur.next;
			// 当前节点的指针,反向指向前一个
			cur.next = first;
			// 这个节点从新作为前节点,等待下一次反向
			first = cur;
			// 从新指定当前节点
			cur = temp;
		}
		node.next = first;
		return node;
	}

 

         4. 对于无头节点的链表,没那么麻烦,仅仅断开第一个节点,从后往前就行了。

 

 

小结:

        1.简单链表,相信大家都懂,各种实现也比我清楚,之所以写这个东西,是因为上次面试有个题,我写了20分钟,想着如何精简代码,如何快速,最后都不敢确定写正确与否,很受打击,也狠狠的鄙视下自己。当然这并不能说明我不会,像很多的排序算法一样,也许我们都知道原理,但是偶尔的一道算法题,不让你上机测试,直接写代码,我相信会有很多人写出来,都不敢保证自己的写的一定正确!确实有一定状态、运气等成分,但是有些基础的东西,以为掌握了,但是在没完全掌握的情况下,还是得进行一些复习吧。

        2.最近看大家聊得最多的什么分布式、高并发、大数据,包括自己也在买书研究,往往忽略的一些基础,也给大家提个醒,抽时间再深入下基础,这些框架实现原理也是基础牢靠了,自己也能实现的,没想象的那么难,最后还是希望大家开心的工作吧~。~

  • 大小: 15.7 KB
  • 大小: 19.5 KB
  • 大小: 18.3 KB
  • 大小: 23.6 KB
  • 大小: 22.6 KB
  • 大小: 20.9 KB
0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics