【数据结构】单链表,双端链表,有序链表

来源:互联网 发布:sql sum group by 编辑:程序博客网 时间:2024/05/29 19:46

    • 单向链表
    • 双端链表
    • 有序链表


在刷LeetCode的时候遇到一道链表的题目 Merge Two Sorted Lists ,发现自己看不懂答案(毕竟没系统学习数据结构,T T) 。

于是乎痛下决心认真实践数据结构的学习。
链表和数组相比,插入和删除数据效率高随机访问某个节点的数据不如数组来得快。

下面是Java实现的各种链表

单向链表

把链表的操作比作针线活,线是每一个节点之间的next
针是复制的所有指向节点的Data

只有next出现在”=“的侧,链表的结构才会发生实质性改变

insertFirst:在表头插入一个新的节点,时间复杂度为O(1)
deleteFirst:删除表头的节点,时间复杂度为O(1)
有了这两个方法,就可以用单链表来实现一个栈了
find:查找包含指定关键字的节点,由于需要遍历查找,平均需要查找N/2次,即O(N)
remove:删除包含指定关键字的节点,由于需要遍历查找,平均需要查找N/2次,即O(N)

public class LinkedList {    public static void main(String[] args) {    }    class Data{        Object obj;        Data next = null;        Data(Object obj){            this.obj = obj;        }    }    Data first = null;    //头节点插入    public void insertFirst(Object obj){        Data data = new Data(obj);        data.next = first;        first = data;    }    //删除头节点    public Object deleteFirst()throws Exception{        if(first==null)            throw new Exception("empty");        Data temp = first;        first = first.next;        return temp.obj;    }    //查找含有指定内容的节点    public Object find(Object obj)throws Exception{        if(first==null)            throw new Exception("empty");        Data cur = first;        while(cur!=null){            if(cur.obj.equals(obj))                return cur.obj;            cur = cur.next;        }        return null;    }    //判断链表是否为空    public boolean isEmpty(){        return first==null;    }    //删除第一个含有指定元素的节点    public void remove(Object obj)throws Exception{        if(first==null)            throw new Exception("empty");        if(first.obj.equals(obj)){   //单次            first = first.next;        }else{            Data pre = first;            Data cur = first.next;            while(cur!=null){                if(cur.obj.equals(obj)){                    pre.next = cur.next;                    break;                }                pre = cur;                cur = cur.next;            }        }    }    //删除所有含有指定元素的节点    public void removeAll(Object obj)throws Exception{        if(first==null)            throw new Exception("empty");        while(first.obj.equals(obj)){            first = first.next;        }        Data pre = first;        Data cur = first.next;        while(cur!=null){            if(cur.obj.equals(obj)){                pre.next = cur.next;                pre = pre.next;                cur = pre.next;  //此时的pre.next跟上一行又不是一回事                continue;   //跳过下面的迭代,继续下一次循环            }            pre = cur;            cur = cur.next;        }    }    //遍历打印    public void display()throws Exception{        if(first == null)            throw new Exception("your list is empty");        Data cur = first;        while(cur!=null){            System.out.print(cur.obj.toString()+"->");            cur = cur.next;        }        System.out.println();    }}
执行结果1 -> 2 -> 3 -> 4 ->   2 -> 3 -> 4 ->   2 -> 4 ->   null  4 

双端链表

双端链表 不是 双向链表 ,双端只不过是保留最后节点的引用(last).

insertFirst:在表头插入一个新的节点,时间复杂度O(1)
insertLast:在表尾插入一个新的节点,时间复杂度O(1)
deleteFirst:删除表头的节点,时间复杂度O(1)
deleteLast::删除表尾的节点,由于只保存了表尾的节点,而没有保存表尾的前一个节点(单向,只能从前往后推),所以在删除表尾节点时需要遍历以找到表尾节点的前一个节点,需查找N-1次,也就是O(N)

用双端链表来实现一个队列

public class FirstLastList {     private class Data{         private Object obj;         private Data next = null;         Data(Object x){             this.obj = x;         }     }     Data first = null;     Data last = null;     public void insertFirst(Object obj){         Data data = new Data(obj);         if(first==null)             last=data;           data.next = first;         first = data;     }    public void insertLast(Object obj){         Data data = new Data(obj);         if(first==null){             first = data;         }else{            last.next = data;         }         last = data;     }    public Object deleteFirst()throws Exception{        if(first==null)            throw new Exception("empty!");        Data temp = first;        if(first.next==null)            last = null;        first = first.next;   //if first.next = null that means first = null        return temp.obj;    }    public void deleteLast()throws Exception{        if(first==null)            throw new Exception("empty!");        if(first.next==null){  //single node scenario            first = null;            last = null;        }else{            Data cur = first;            while(cur.next!=null){  //stop by end                if(cur.next==last){                    last = cur;                    last.next = null;                    break;   //这个break似乎没卵用啊?? 反正都到最后一个点了  加上也就少执行一次cur = cur.next                }                cur = cur.next;            }        }    }    public void display()throws Exception{        if(first == null)            throw new Exception("your list is empty");        Data cur = first;        while(cur!=null){            System.out.print(cur.obj.toString()+"->");            cur = cur.next;        }        System.out.println();    }    public static void main(String[] args) throws Exception {     FirstLastList fll = new FirstLastList();          fll.insertFirst(2);          fll.insertFirst(1);          fll.display();          fll.insertLast(3);          fll.display();          fll.deleteFirst();          fll.display();          fll.deleteLast();          fll.display();      }}
执行结果    1 -> 2 ->       1 -> 2 -> 3 ->       2 -> 3 ->       2 ->   

有序链表

单向链表在插入的时候排个序而已。

表的插入和删除平均需要比较N/2次,即O(N),但是获取最小数据项只需O(1),因为其始终处于表头,对频繁操作最小数据项的应用,可以考虑使用有序链表实现,如:优先级队列

public class SortedList {     private class Data{              private Object obj;              private Data next = null;              Data(Object obj){                  this.obj = obj;              }          }       private Data first = null;     public void insert(Object obj){         Data data = new Data(obj);         Data pre = null;         Data cur = first;         while(cur!=null&&Integer.valueOf(data.obj.toString()).intValue()>         Integer.valueOf(cur.obj.toString()).intValue()){             pre = cur;             cur = cur.next;         }         if(pre==null)             first = data;         else             pre.next = data;         data.next = cur;     }     public Object deleteFirst()throws Exception{         if(first==null)             throw new Exception("empty");         Data temp = first;         first = first.next;         return temp.obj;     }     public void display(){         if(first == null)                  System.out.println("empty");              System.out.print("first -> last : ");              Data cur = first;              while(cur != null){                  System.out.print(cur.obj.toString() + " -> ");                  cur = cur.next;              }              System.out.print("\n");     }     public static void main(String[] args) throws Exception{         SortedList sl = new SortedList();              sl.insert(80);              sl.insert(2);              sl.insert(100);              sl.display();              System.out.println(sl.deleteFirst());              sl.insert(33);              sl.display();              sl.insert(99);              sl.display();      }}
执行结果first -> last : 2 -> 80 -> 100 -> 2first -> last : 33 -> 80 -> 100 -> first -> last : 33 -> 80 -> 99 -> 100 -> 
0 0
原创粉丝点击