①泡茶看数据结构-表ADT

简介:
  表ADT节点:

              #单链表

              #双链表

              #循环链表

              #浅谈面试题一道

 
                                     
                喝一口热热的茶,算法和数据结构虽然枯燥,希望我不讲的枯燥。毛尖还是淡淡的味道,非常喜欢。
 

回顾

    ①ADT:带一组操作的一些对象的集合:对象及对象的操作。
    ②java考虑了ADT实现,隐藏了实现的细节。
 

单链表

    ①链表中的数据是以节点来表示的,每个节点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个节点的地址数据。
 
              
 
  上面是比较官方的,我的版本就像老式火车一样:火车节号→火车里面东西
 
              
 
  ②思考
 
    相比表的数组实现,单链表的好处明显的两点:避免了插入和删除的开销。还有值得说的一点,改变表的起始端(表头和亚节点)。以下是我的 观点:如果像一些查询较多的应用,数组和链表都行。但像有些,更新和插入,删除多的情况,比如游戏中的装备等,就应该选择考虑下链表。这就是学这些的 nice point。
 
                    
                   它冒着热气,像是生活,coding生活那样有味。
   ③例子来一枚-java
package LinkedList;   
  
/**  
 * <p><strong>我的Java单链表练习</strong></p>  
 * <p>单链表提供了在列表头的高效插入和删除操作,不过在单链表的末尾的插入操作效率很低.</p>  
 * <p>单链表指针域保存着下一节点的引用,尾结点的指针域等于null</p>  
 * @author baby69yy2000  
 */  
public class SingleLinkedList<T> {   
       
    /**  
     * 结点类  
     */  
    private static class Node<T> {   
        T nodeValue; // 数据域   
        Node<T> next; // 指针域保存着下一节点的引用   
           
        Node(T nodeValue, Node<T> next) {   
            this.nodeValue = nodeValue;   
            this.next = next;   
        }   
           
        Node(T nodeValue) {   
            this(nodeValue, null);   
        }   
    }   
  
    // 下面是SingleLinkedList类的数据成员和方法   
    private Node<T> head, tail;   
       
    public SingleLinkedList() {   
        head = tail = null;   
    }   
       
    /**  
     * 判断链表是否为空  
     */  
    public boolean isEmpty() {   
        return head == null;   
    }   
       
    /**  
     * 创建头指针,该方法只用一次!  
     */  
    public void addToHead(T item) {   
        head = new Node<T>(item);   
        if(tail == null) tail = head;   
    }   
       
    /**  
     * 添加尾指针,该方法使用多次  
     */  
    public void addToTail(T item) {   
        if (!isEmpty()) { // 若链表非空那么将尾指针的next初使化为一个新的元素   
            tail.next = new Node<T>(item); // 然后将尾指针指向现在它自己的下一个元素   
            tail = tail.next;   
        } else { // 如果为空则创建一个新的!并将头尾同时指向它   
            head = tail = new Node<T>(item);         
        }   
    }   
       
    /**  
     * 打印列表  
     */  
    public void printList() {   
        if (isEmpty()) {   
            System.out.println("null");   
        } else {   
            for(Node<T> p = head; p != null; p = p.next)   
                System.out.println(p.nodeValue);   
        }   
    }   
       
    /**  
     * 在表头插入结点,效率非常高  
     */  
    public void addFirst(T item) {   
        Node<T> newNode = new Node<T>(item);   
        newNode.next = head;   
        head = newNode;   
    }   
       
    /**  
     * 在表尾插入结点,效率很低  
     */  
    public void addLast(T item) {   
        Node<T> newNode = new Node<T>(item);   
        Node<T> p = head;   
        while (p.next != null) p = p.next;   
        p.next = newNode;   
        newNode.next = null;   
    }   
       
    /**  
     * 在表头删除结点,效率非常高  
     */  
    public void removeFirst() {   
        if (!isEmpty()) head = head.next;   
        else System.out.println("The list have been emptied!");   
    }   
       
    /**  
     * 在表尾删除结点,效率很低  
     */  
    public void removeLast() {   
        Node<T> prev = null, curr = head;   
        while(curr.next != null) {   
            prev = curr;   
            curr = curr.next;   
            if(curr.next == null) prev.next = null;   
        }   
    }   
       
    /**  
     * <p>插入一个新结点</p>  
     * <ul>插入操作可能有四种情况:  
     * <li>①表为空, 返回false</li>  
     * <li>②表非空,指定的数据不存在</li>  
     * <li>③指定的数据是表的第一个元素</li>  
     * <li>④指定的数据在表的中间</li></ul>  
     * @param appointedItem 指定的nodeValue  
     * @param item 要插入的结点  
     * @return 成功插入返回true;  
     */  
    public boolean insert(T appointedItem, T item) {   
        Node<T>  prev = head, curr = head.next, newNode;   
        newNode = new Node<T>(item);   
        if(!isEmpty()) {   
            while((curr != null) && (!appointedItem.equals(curr.nodeValue))) { //两个判断条件不能换   
                prev = curr;   
                curr = curr.next;   
            }   
            newNode.next = curr; //②③④   
            prev.next = newNode;   
            return true;    
        }   
        return false; //①   
    }   
       
    /**  
     * <p>移除此列表中首次出现的指定元素</p>  
     * <ul>删除操作可能出现的情况:  
     * <li>①prev为空,这意味着curr为head. head = curr.next; --> removeFirst();</li>  
     * <li>②匹配出现在列表中的某个中间位置,此时执行的操作是 --> prev.next = curr.next;,</li></ul>  
     * <p>在列表中定位某个结点需要两个引用:一个对前一结点(prev左)的引用以及一个对当前结点(curr右)的引用.</p>  
     * prev = curr;  
     * curr = curr.next;  
     */  
    public void remove(T item) {   
        Node<T> curr = head, prev = null;   
        boolean found = false;   
        while (curr != null && !found) {   
            if (item.equals(curr.nodeValue)) {   
                if(prev == null) removeFirst();   
                else prev.next = curr.next;   
                found = true;   
            } else {   
                prev = curr;   
                curr = curr.next;   
            }   
        }   
    }   
       
    /**  
     * 返回此列表中首次出现的指定元素的索引,如果列表中不包含此元素,则返回 -1.  
     */  
    public int indexOf(T item) {   
        int index = 0;   
        Node<T> p;   
        for(p = head; p != null; p = p.next) {   
            if(item.equals(p.nodeValue))   
                return index;   
            index++;   
                   
        }   
        return -1;   
    }   
       
    /**  
     * 如果此列表包含指定元素,则返回 true。  
     */  
     public boolean contains(T item) {   
         return indexOf(item) != -1;   
     }   
       
    public static void main(String[] args) {   
        SingleLinkedList<String> t = new SingleLinkedList<String>();   
        t.addToHead("A");   
        //t.addFirst("addFirst");   
        t.addToTail("B");   
        t.addToTail("C");   
        System.out.println(t.indexOf("C")); // 2   
        System.out.println(t.contains("A")); // true   
        //t.addLast("addLast");   
        //t.removeLast();   
        //t.insert("B", "insert");   
        //t.removeFirst();   
        //t.remove("B"); // A C   
        t.printList(); // A B C   
           
    }   
  
}

 双链表  

  
    ①双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。
 
                
 
    就像火车也升级了,我们一般都用双链表。快捷
 
               
  
    ②思考
       相对单链表,这貌似给我们社会进步意义一样。更容易让我们随心所欲。自然这条路走过了是艰难的。
 

循环链表

 
  ①循环链表是另一种形式的链式存贮结构。它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环。
 
              
 
    我认为像小孩子牵着手:童真的我
 
          
相关文章
|
2月前
|
存储 算法 索引
【数据结构入门精讲 | 第四篇】考研408、企业面试表专项习题
【数据结构入门精讲 | 第四篇】考研408、企业面试表专项习题
52 0
|
2月前
|
存储
【数据结构入门精讲 | 第三篇】一文讲清表
【数据结构入门精讲 | 第三篇】一文讲清表
24 0
|
3月前
|
存储 Rust C语言
【一起学Rust | 进阶篇 | Grid库】二维表数据结构——Grid
【一起学Rust | 进阶篇 | Grid库】二维表数据结构——Grid
83 0
|
5月前
|
SQL Oracle 关系型数据库
PL/SQL生成表的数据结构关系图
PL/SQL生成表的数据结构关系图
|
存储 算法
【数据结构和算法】图的各类概念与图的存储结构(还有十字链表与邻接多重表的介绍)
【数据结构和算法】图的各类概念与图的存储结构(还有十字链表与邻接多重表的介绍)
169 0
【数据结构和算法】图的各类概念与图的存储结构(还有十字链表与邻接多重表的介绍)
|
10月前
|
存储 索引
《数据结构导论》之查找表
我们知道,将数据采用顺序存储或者链式存储等多种方式存储不是最终目的,我们要使用存储的数据,发挥它的作用。但是,在使用数据时,要先对数据进行查找,在日常生活和各种软件系统中,查找是一种十分常见的操作,下面我为大家讲解一下我对查找表的理解。
算法与数据结构全阶班-左程云版(二)基础阶段之2.链表、栈、队列、递归行为、哈希表和有序表(下)
本文主要介绍了一些常用的数据结构,包括链表、栈、队列、递归、哈希表和有序表。
算法与数据结构全阶班-左程云版(二)基础阶段之2.链表、栈、队列、递归行为、哈希表和有序表(下)
|
算法 Java API
算法与数据结构全阶班-左程云版(二)基础阶段之2.链表、栈、队列、递归行为、哈希表和有序表(上)
本文主要介绍了一些常用的数据结构,包括链表、栈、队列、递归、哈希表和有序表。
算法与数据结构全阶班-左程云版(二)基础阶段之2.链表、栈、队列、递归行为、哈希表和有序表(上)
|
存储 Java
数据结构——哈希表
数据结构——哈希表
82 0
数据结构——哈希表
【数据结构408考研收藏】ADT线性表、树、图
【数据结构408考研收藏】ADT线性表、树、图
78 0
【数据结构408考研收藏】ADT线性表、树、图