有序链表

  1. 有序链表数据结构(同单链表)

    有序链表添加新的元素:

    头插法 <新节点的数据项小于头节点 或者 链表为空>:

    开始插入之前<链表为空>:

    开始插入之前<新节点数据项小于头节点>:

    插入之后:

    链表元素个数>=1

    在某个特定元素后面添加元素:

    <在node1之后插入node2元素>

    publicboolean insertAfter(LinkNode node1,LinkNode node2);

    有序链表删除特定数据元素:

    删除头节点:

 

删除非头节点:

 

有序链表的查找:

Current 指针依次遍历有序链表直到找到目标数据项

  1.  ADT
    • //有序链表:单链表节点实现 实质为单链表
      public class  SortedList {
          private static LinkNode first;
       //构造方法 用LinkNode数组初始化 有序链表
          public   SortedList(LinkNode[] nodes);
          public static boolean isEmpty();
           //O[N] 从链表头部插入一个元素 找到第一个比输入参数大的节点插入该位置
          public void insert (LinkNode node);
          //O[1] 从链表头部删除一个元素
          public LinkNode deleteFirst();
          //O[N]从链表头到尾部显示每个节点
          public void displayList();
          //O[N] 查找到某个特定节点
          public LinkNode findNode(double value);
          //o[N] 删除某个特定节点
              public LinkNode deleteNode(LinkNode l);                                                                                           
           //o[N]在某个特定节点node1后插入一个节点node2
              public boolean insertAfter(LinkNode node1,LinkNode node2);
          }
  2. 程序
    • public class  SortedList {
          private static LinkNode first;
       
          public static LinkNode getFirst() {
              return first;
          }
           
          public   SortedList( ){
              first = null;
          }
          public   SortedList(LinkNode[] nodes){
              //initailize list copy arry to the SortedList
              first = null;
              for(int j=0;j<nodes.length;j++){ 
                  insert(nodes[j]);
              }
              
          }
          public static boolean isEmpty(){
              return (first==null);
          }
          //找到第一个比输入参数大的节点插入该位置 
          public void insert (LinkNode node){//O[N]
              LinkNode current = first;
              LinkNode pre = null;
              while(current!=null&&current.iData<node.iData){
                  pre = current;
                  current = current.next;
              }
              node.next = current;
              if(pre==null){  
                  first = node; 
              }else{
                  pre.next = node;
              }
          }
          public LinkNode deleteFirst(){//O[1]
              if (isEmpty()){
                  return null;
              }
              LinkNode temp = first;
              first = first.next;
              return temp;
          }
          public void displayList(){
              System.out.println(" List (first-->last): ");
              LinkNode current = first;
              while (current!=null){
                  current.displayLink();
                  current = current.next;
              }
              System.out.println("");
          }
          public LinkNode findNode(double value){
              LinkNode current = first;
               while (current!=null){
              //     current.displayLink();
                   if(current.dData ==value){
                       return current;
                       }
                      current = current.next;
                   }
                  return null;
              }
              public LinkNode deleteNode(LinkNode l){     //o[n]                                                    
                    LinkNode current = first;                                                                   
                    LinkNode pre = current;                                                                     
                    while (current!=null){//the  loop end condition:traverse to the last node of the link       
                        if(current.dData == l.dData && current.iData==l.iData){//find the node                    
                          if(current == first) first = first.next;                                                
                            pre.next = current.next;                                                                
                            return current;                                                                         
                        }else{//go on to find it                                                                  
                            pre = current;                                                                          
                            current = pre.next;                                                                     
                        }                                                                                         
                    }                                                                                           
                    return null;                                                                                
                }                                                                                             
                                                                                                            
           
              public boolean insertAfter(LinkNode node1,LinkNode node2){
                  //找到这个特定节点
                   LinkNode  target = findNode(node1.dData);
                   System.out.println("target  ");
                   target.displayLink();
                   if (target!=null){
                       node2.next         = target.next; 
                       target.next= node2;
                       return true;
                   }
                  return false;
              }
          }
      public class SortedListApp {
          public static void main(String[] args) {
              //make a new list
              SortedList sl = new SortedList();
              sl.insert(new LinkNode(11,11.11));
              sl.insert(new LinkNode(33,33.33));    
              sl.insert(new LinkNode(44,44.44));
              sl.insert(new LinkNode(66,66.66));
              sl.insert(new LinkNode(55,55.55));
              sl.displayList();
          }
      }
  3. 有序链表的应用
    1. 表插入排序
      1. 概要
      • 有序链表可以用于一种高效的排序机制。
        主要步骤:
        1 准备待排序数组
        1 初始化链表,将数组数据插入链表中 
        2  遍历链表寻找插入位置  
        3 记录插入链表中
        4 将链表数据元素删除,并将删除的元素记录到数组之中
      1. 代码
        1. LinkList 引用1.2.2 程序
          SortedList 引用 2.3 程序
        2. public class ListInsertionSortArray {
              private SortedList s1;//有序链表作为工具属性 
              private int[] arr;//待排序的数组
              //O[N^2] 
              /*构造方法:
              1 准备待排序数组
              2 初始化链表,将数组数据插入链表中 
              3  遍历链表寻找插入位置  
              4 记录插入链表中*/
              public ListInsertionSortArray(int[] arr){
                  this.arr = arr;
                  LinkNode[] linkNodes = new LinkNode[arr.length];
                  System.out.println("有序链表排序之前");
                  for(int i=0;i<arr.length;i++){
                      //将输入参数 数组变成有序链表节点数组 Link[]
                      System.out.print(arr[i]+" ");
                      LinkNode link = new LinkNode (arr[i],arr[i]+0.1);
                      linkNodes[i] = link;
                  }
                  s1 = new SortedList(linkNodes);
                  System.out.println();
              }
              //4 将链表数据元素删除,并将删除的元素记录到数组之中  算法时间复杂度 :O[N]
              public int[] sortArr(){
                  for(int j=0;j<arr.length;j++){
                      arr[j] = s1.deleteFirst().iData;
                  }
                  return arr;
              }
          }
        3. public class ListInsertionSortArrayApp {
              public static void main(String[] args) {
                  int[] arr = {10,20,78,67,6,1};//待排序数组
                  ListInsertionSortArray listSortArr =// 
                          new ListInsertionSortArray(arr);
                  arr = listSortArr.sortArr();
                  System.out.println("有序链表排序之后 :");
                  for(int i = 0;i<arr.length;i++){
                      System.out.print(arr[i]+"  ");
                  }
              }
          }
      2. 效率分析
      •  平均时间和最坏情况下(待排序序列逆序)时间复杂度o(n^2),
         再来看一下最佳情况(待排序序列有序), 关键字比较次数并为o(1),时间复杂度为o(n). 
    2. 优先级队列
      • 根据有序链表的特点:在有序链表中,数据是按照关键值有序排列的,有序链表的删除,常常只限定于删除在链表头部的最小或者最大的节点。
        如果一个应用频繁的存取最小项(或者最大项) 且不需要快速的插入 .在抢占式多任务操作系统中,程序就在优先级队列中排序。.那么考虑使用优先级队列.
        优先级队列和队列的区别就是,优先级队列是按关键字排序的。而每次新数据进入队列,也会根据需要将数据插入到应该的位置,以便确保队列的顺序。
      • 优先级队列特点:
            first in first out(先进先出)
        方法总结:
        Queue 
        insert() //链表尾部插入一个新的元素
        remove()//链表头部删除一个元素
        peekFront()//查询链表最前端的一个元素
        size()//链表元素个数
      • ADT
        • class PriorityQ
             { //-------------------------------------------------------------
             public void insert(long item) ;   // insert item 
          //-------------------------------------------------------------
             public long remove()     ;        // remove minimum item 
          //-------------------------------------------------------------
             public long peekFront()          ;  // peek at minimum item 
          //-------------------------------------------------------------
             public boolean isEmpty()     ;    // true if queue is empty  
          //-------------------------------------------------------------
           }  // end class PriorityQ
      • 代码
        • class PriorityQ
          {    //有序链表 
              private SortedList list;
              public PriorityQ(){
                  list = new SortedList();
              }
              //链表尾部插入一个新的元素
              public void insert(LinkNode node){
                  list.insert(node);
              } 
              //链表头部删除一个元素
              public LinkNode remove(){
                  return list.deleteFirst();
              }
              //查询链表最前端的一个元素
              public LinkNode peekFront(){
                  return list.getFirst();
              }
              public void display(){
                  list.displayList();
              }
              public boolean isEmpty(){return list.isEmpty();}
          }  // end class PriorityQ
          ////////////////////////////////////////////////////////////////
          class PriorityQApp
          {
          public static void main(String[] args)
             {
                 PriorityQ thePQ = new PriorityQ( );
                    thePQ.insert(new LinkNode(30,30.1));
                    thePQ.insert(new LinkNode(50,50.1));
                    thePQ.insert(new LinkNode(10,10.1));
                    thePQ.insert(new LinkNode(40,40.1));
                    thePQ.insert(new LinkNode(20,20.1));
          
                    while( !thePQ.isEmpty() )
                       {
                       int item = thePQ.remove().iData ;
                       System.out.print(item + " ");  // 10, 20, 30, 40, 50
                       }  // end while
                    System.out.println("");
             }
            
          }  // end class PriorityQApp
          ////////////////////////////////////////////////////////////////
    3. 其他应用程序
      1. 单词字典顺序排序
        • 编写一个程序,将所有输入的单词按字典顺序输出,不区分大小写。
          输入:测试数据不超过5000行,每行不超过200个字符。EOF结束输入。
          输出:所有输出皆为小写形式。每行输出一个单词。
          例如 : 
              输入 : you are the best one
              输出 : are best one the you
        • 1 将字符串拆分为 String[]
          2 将字符数据转化为:数据域为char数组类型的单链表节点
          3 将上述节点插入到有序数组之中
          4 将有序数组中的元素逐一删除,并装重新入String[]
          5 返回数据
        • 链表节点代码
          • public interface Node {
                public Object data = null;
                public Node next=null;
                public void display();
            }
        • 有序链表
          • public class CharListNode  implements Node {
                public char[] data ;
                public CharListNode next;
                
                public CharListNode(char[] data) {
                    super();
                    this.data = data;
                    this.next = null;
                }
                public void display() {
                    System.out.print(new String(data)+"  ");
                }
            
            }
        • APP
          • public class OutPutWordInDictionaryOrder  {
                        /*
                        1 将字符串拆分为 String[]
                        2 将字符数据转化为:数据域为char数组类型的单链表节点
                        3 将上述节点插入到有序数组之中
                        4 将有序数组中的元素逐一删除,并装重新入String[]
                        5 返回数据*/
                //辅助工具类有序链表
                public static SortedCharListLink link = new SortedCharListLink();
                //输入字符串
                public static String input = " ";
                //链表的各个节点组成的数组
                static CharListNode[] nodes ;
                public OutPutWordInDictionaryOrder(String input){
                    this.input = input;
                }
                public static String sortWordOrder( ){
                    String result ="";
                    String[] strs = input.split(" ");
                    nodes = new CharListNode[strs.length];
                    for(int i=0;i<strs.length;i++){
                        nodes[i] = new CharListNode(strs[i].toCharArray());
                        link.insert(nodes[i]);
                    }
                    for(int i=0;i<strs.length;i++){
                        char[] chars = (char[]) link.deleteFirst().data;
                         result += new String(chars)+" ";
                    }
                    return result;
                }
                public static void main(String[] args) {
                    String input = "you are not bad girl";
                    System.out.println("原始的字符串是 :"+input);
                    OutPutWordInDictionaryOrder o = new OutPutWordInDictionaryOrder("you are not bad girl");
                    String result = o.sortWordOrder();
                    
                    System.out.println("排序后的字符串是 :"+result) ;
                }
            }
      2. 反向输出字符串
        1. 链表节点
          1. /*数据域为 char 类型的单链表节点*/
            public class CharLinkNode implements Node{
                public char  data;
                public CharLinkNode next;
                
                public CharLinkNode(char data){
                    this.data = data; 
                }
                public void setData(char  data){
                    this.data = data;
                }
                public char  getData(){
                    return this.data ;
                }
             
                public void setNext(CharLinkNode next) {
                    this.next = next;
                }
                public void display(){
                    String str = new String();
                    System.out.print(data+"  ");
                }
            }
        2. /*有序单链表*/
          public class SortedCharLink {
              private CharLinkNode first;
              public SortedCharLink(){
                  
              }
              public SortedCharLink(CharLinkNode[] links){
                  //initailize list copy arry to the SortedList
                  first = null;
                  for(int i=0;i<links.length;i++){
                       insert(links[i]);
                  }
              }
              public boolean isEmpty(){
                  return first==null;
              }
              /*O[1]*/
              public CharLinkNode remove(){
                  CharLinkNode link = first;
                  first = first.next;
                  return link;
              }
              /*O[N]*/
              public void insert(CharLinkNode linkNode){
                  CharLinkNode current=first;
                  CharLinkNode pre = null;
                  //找出新节点的位置
                  while(current!=null&&current.getData()>linkNode.getData()){
                      pre = current;
                      current = current.next;
                  }
                  if(pre!=null){
                      pre.next= linkNode;
                      linkNode.setNext(current);
                  }else{
                      linkNode.next = first;
                      first  = linkNode;
                  }
              }
              public void displayList(){
                  CharLinkNode current=first;
                  System.out.println("Display Order: from front to end");
                  while(current!=null){
                      System.out.print
                      (current+" -- ");
                      current = current.next;
                  }
                  System.out.println();
              }
              public static void main(String[] args) {
                  System.out.println('a'>'b');
              }
          }
        3. /*利用栈的特性将字符串反向输出
           * input :输入的字符串
           * output:反向输出的字符串
           * */
          public class Reverser {
              private String input;
              private String output;
              public Reverser(String in){
                  input=in;
              }
              public String doReverse(){
                  String result = "";
                  //将输入字符串转化为char字符数组
                  char[] chars = input.toCharArray(); 
                  CharLinkNode[] nodes = new CharLinkNode[chars.length] ;
                  //将每个 char字符分别装入对应的链表节点当中
                  for(int i=0;i< chars.length;i++){
                      nodes[i] = new CharLinkNode(chars[i] ); 
                  }
                  SortedCharLink link = new SortedCharLink(nodes);
                  //初始化节点数组
                  for(int i=0;i<chars.length;i++){
                      chars[i]=link.remove().getData();
                  }
                  result = new String(chars);
                  this.output = result;
                  return output;
              }
          }
        4. public class ReverserApp {
              public static void main(String[] args) {
                  Reverser rs = new Reverser("abcdefg");
                  System.out.println(rs.doReverse());
              }
          }

        

 

 

 

 

 

 

posted @ 2013-06-23 23:22  王超_cc  阅读(2240)  评论(0编辑  收藏  举报