<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    E81086713E446D36F62B2AA2A3502B5EB155

    Java雜家

    雜七雜八。。。一家之言

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      40 Posts :: 1 Stories :: 174 Comments :: 0 Trackbacks

    #

    外部排序實現使用堆來生成若干個順串,然后使用多路歸并算法來生成最終排序好的內容。

    本來打算使用敗者樹,結果發現敗者樹當參與的競賽者相對較多的情況下,沒有全部完成就被空節點充滿了。
    這個按照它的嚴格算法,其實也是可以知道不能保證總是能排完的。天快亮了,才徹底放棄使用敗者樹。改成實現贏者樹,結果發現贏者樹能保證不出錯,實現竟也順手。

    最后整了個測試文件500M的隨機內容,2~3分鐘排序完成了(應該還可以優化),感覺還行。

    代碼較多,最要考慮到以后可能要重用。

    package algorithms.extsort;

    import java.io.IOException;

    import algorithms.MinHeap;

    /**
     * 
    @author yovn
     *
     
    */
    public class ExternalSorter {
        
            
        
        
    public void sort(int heapSize,RecordStore source,RunAcceptor mediator ,ResultAcceptor ra)throws IOException
        {
            MinHeap
    <Record> heap=new MinHeap<Record>(Record.class,heapSize);
            
    for(int i=0;i<heapSize;i++)
            {
                Record r
    =source.readNextRecord();
                
    if(r.isNull())break;
                heap.insert(r);
            }
            
            Record readR
    =source.readNextRecord();
            
    while(!readR.isNull()||!heap.isEmpty())
            {
            
                Record curR
    =null;
                
    //begin output one run
                mediator.startNewRun();
                
    while(!heap.isEmpty())
                {
                    curR
    =heap.removeMin();
                
                    mediator.acceptRecord(curR);
                    
                    
    if (!readR.isNull()) {
                        
    if (readR.compareTo(curR) < 0) {
                            heap.addToTail(readR);
                        } 
    else
                            heap.insert(readR);
                    }
                    readR
    =source.readNextRecord();
                    
                }
                
    //done one run
                mediator.closeRun();
                
                
    //prepare for next run
                heap.reverse();
                
    while(!heap.isFull()&&!readR.isNull())
                {
                    
                    heap.insert(readR);
                    readR
    =source.readNextRecord();
                    
                }
                
                
            }
            RecordStore[] stores
    =mediator.getProductedStores();
    //        LoserTree  lt=new LoserTree(stores);
            WinnerTree  lt=new WinnerTree(stores);
            
            Record least
    =lt.nextLeastRecord();
            ra.start();
            
    while(!least.isNull())
            {
                ra.acceptRecord(least);
                least
    =lt.nextLeastRecord();
            }
            ra.end();
            
            
    for(int i=0;i<stores.length;i++)
            {
                stores[i].destroy();
            }
        }
        
        
        
    public static void main(String[] args) throws IOException
        {
    //        RecordStore store=new MemRecordStore(60004,true);
    //        RunAcceptor mediator=new MemRunAcceptor();
    //        ResultAcceptor ra=new MemResultAcceptor();
            ExternalSorter sorter=new ExternalSorter();
                
            RecordStore store
    =new FileRecordStore("test_sort.txt");
            RunAcceptor mediator
    =new FileRunAcceptor("test_sort");
            ResultAcceptor ra
    =new FileRecordStore("test_sorted.txt");
            
            
            sorter.sort(
    70000, store, mediator, ra);
        }
        
    }

    其余的都打包在此!

    源碼

    posted @ 2007-12-16 08:08 DoubleH 閱讀(3342) | 評論 (3)編輯 收藏

    六。 最小支撐樹MST
    給定一個簡單有向圖,要求權值最小的生成樹,即求最小支撐樹問題。
    所謂生成樹,就是說樹的頂點集合等于給定圖的頂點集合,且邊集合包含于圖的邊集合。
    也就說找出構成樹的,經過所有頂點的,且權值最小的邊集。
    樹的定義是要求無回路的,然后是要求連通的。

    有兩個比較經典的算法是:
    1)Prim算法: 該算法的思想跟Dijstra算法非常相似,Dijstra算法中每次求出下一個頂點時依據的是離初始頂點最近的,而Prim算法則找離V1整個集合最近的,也就是從V1中某個節點出發到該頂點的邊的權值最小。
    其原理也是每次找局部最優,最后構成全局最優。
    實現如下

    @Override
        
    public Edge[] prim() {
            MinHeap
    <Edge> heap=new MinHeap<Edge>(Edge.class,numEdges);
            Edge[] edges
    =new Edge[numVertexes-1];
            
    //we start from 0
            int num=0;//record already how many edges;
            int startV=0;
            Arrays.fill(visitTags, 
    false);
            Edge e;
            
    for(e=firstEdge(startV);isEdge(e);e=nextEdge(e))
            {
                heap.insert(e);
            }
            visitTags[startV]
    =true;
            
            
    while(num<numVertexes-1&&!heap.isEmpty())//tree's edge number was n-1
            {
                
                e
    =heap.removeMin();
            
                startV
    =toVertex(e);
                
    if(visitTags[startV])
                {
                    
    continue;
                }
                visitTags[startV]
    =true;
                edges[num
    ++]=e;
                
    for(e=firstEdge(startV);isEdge(e);e=nextEdge(e))
                {
                    
    if(!visitTags[toVertex(e)])//can't add already visit vertex, this may cause cycle
                    heap.insert(e);
                }
                
                    
                
            }
            
    if(num<numVertexes-1)
            {
                
    throw new IllegalArgumentException("not connected graph");
            }
            
    return edges;
        }

    /**
         * A Graph example
         * we mark the vertexes  with 0,1,2,.14 from left to right , up to down
         * S-8-B-4-A-2-C-7-D
         * |   |   |   |   |
         * 3   3   1   2   5
         * |   |   |   |   |
         * E-2-F-6-G-7-H-2-I
         * |   |   |   |   |
         * 6   1   1   1   2
         * |   |   |   |   |
         * J-5-K-1-L-3-M-3-T
         * 
         
    */
        
    public static void testPrimMST() {
        

            
            DefaultGraph g
    =new DefaultGraph(15);
            g.setEdge(
    018);
            g.setEdge(
    108);//its a undirected graph
            g.setEdge(124);
            g.setEdge(
    214);
            g.setEdge(
    232);
            g.setEdge(
    322);
            g.setEdge(
    347);
            g.setEdge(
    437);
            
            g.setEdge(
    053);
            g.setEdge(
    503);
            g.setEdge(
    163);
            g.setEdge(
    613);
            g.setEdge(
    271);
            g.setEdge(
    721);
            g.setEdge(
    382);
            g.setEdge(
    832);
            g.setEdge(
    495);
            g.setEdge(
    945);
            
            
            g.setEdge(
    562);
            g.setEdge(
    652);
            g.setEdge(
    676);
            g.setEdge(
    766);
            g.setEdge(
    787);
            g.setEdge(
    877);
            g.setEdge(
    892);
            g.setEdge(
    982);
            
            
            g.setEdge(
    1056);
            g.setEdge(
    5106);
            g.setEdge(
    1161);
            g.setEdge(
    6111);
            g.setEdge(
    1271);
            g.setEdge(
    7121);
            g.setEdge(
    1381);
            g.setEdge(
    8131);
            g.setEdge(
    1492);
            g.setEdge(
    9142);
            
            g.setEdge(
    10115);
            g.setEdge(
    11105);
            g.setEdge(
    11121);
            g.setEdge(
    12111);
            g.setEdge(
    12133);
            g.setEdge(
    13123);
            g.setEdge(
    13143);
            g.setEdge(
    14133);
            
            g.assignLabels(
    new String[]{"S","B","A","C","D","E","F","G","H","I","J","K","L","M","T"});
            Edge[] edges
    =g.prim();
            
    int total=0;
            
    for(int i=0;i<edges.length;i++)
            {
                System.out.println(edges[i].toString(g));
                total
    +=edges[i].getWeight();
            }
            System.out.println(
    "MST total cost:"+total);
    }

    2)Kruskal算法:
    該算法開始把,每個節點看成一個獨立的兩兩不同的等價類,每次去權值最小的邊,如果關聯這條邊的兩個頂點在同一個等價類里那么這條邊不能放入MST(最小生成樹)中,否則放入MST中,并把這兩個等價類合并成一個等價類。
    繼續從剩余邊集里選最小的邊,直到最后剩余一個等價類了。
    該算法涉及等價類的合并/查找,一般用父指針樹來實現。下面先給出父指針樹實現的并查算法。
    帶路徑壓縮的算法,其查找時間代價可以看做是常數的。

    package algorithms;

    /**
     * 
    @author yovn
     *
     
    */
    public class ParentTree {
        
        
        
    private static class PTreeNode
        {
            
    int parentIndex=-1;
            
    int numChildren=0;//only make sense in root

            
    void setParent(int i) {
                
                parentIndex
    =i;
                
            }
        }
        PTreeNode[] nodes;
        
    int numPartions;
        
    public ParentTree(int numNodes)
        {
            nodes
    =new PTreeNode[numNodes];
            numPartions
    =numNodes;
            
    for(int i=0;i<numNodes;i++)
            {
                nodes[i]
    =new PTreeNode();
                nodes[i].parentIndex
    =-1;//means root
                
            }
            
        }
        
        
    /**
         * use path compress
         * 
    @param i
         * 
    @return
         
    */
        
    public int find(int i)
        {
            
    if(nodes[i].parentIndex==-1)
            {
                
    return i;
            }
            
    else
            {
                nodes[i].setParent(find(nodes[i].parentIndex));
    //compress the path
                return nodes[i].parentIndex;
            }
        }
        
        
    public int numPartions()
        {
            
    return numPartions;
        }
        
    public boolean union(int i,int j)
        {
            
    int pi=find(i);
            
    int pj=find(j);
            
    if(pi!=pj)
            {
                
    if(nodes[pi].numChildren>nodes[pj].numChildren)
                {
                    nodes[pj].setParent(pi);
                    nodes[pj].numChildren
    +=nodes[pi].numChildren;
                    nodes[pi].numChildren
    =0;
                    
                }
                
    else
                {
                    nodes[pi].setParent(pj);
                    nodes[pi].numChildren
    +=nodes[pj].numChildren;
                    nodes[pj].numChildren
    =0;
                }
                numPartions
    --;
                
    return true;
            }
            
    return false;
        }
        
    }


    從邊集里權最小的邊,我們又可以借助最小值堆來完成。有了父指針樹以及最小值堆,現實Kruskal算法就很簡單了:

    @Override
        
    public Edge[] kruskal() {
            Edge[] edges
    =new Edge[numVertexes-1];
            ParentTree ptree
    =new ParentTree(numVertexes);
            MinHeap
    <Edge> heap=new MinHeap<Edge>(Edge.class,numEdges);
            
    for(int i=0;i<numVertexes;i++)
            {
                
    for(Edge e=firstEdge(i);isEdge(e);e=nextEdge(e))
                {
                    heap.insert(e);
                }
            }
            
    int index=0;
            
    while(ptree.numPartions()>1)
            {
                Edge e
    =heap.removeMin();
                
    if(ptree.union(fromVertex(e),toVertex(e)))
                {
                    edges[index
    ++]=e;
                }
            }
            
    if(index<numVertexes-1)
            {
                
    throw new IllegalArgumentException("Not a connected graph");
            }
            
    return edges;
            
        }
    OK,到此,圖論的大概的算法算是復習完了。

    posted @ 2007-12-14 23:48 DoubleH 閱讀(3680) | 評論 (1)編輯 收藏

         摘要: 四 拓撲排序 考慮一個任務安排的例子,比如有很多任務T1,T2,.... 這些任務又是相互關聯的,比如Tj完成前必須要求Ti已完成,這樣T1,T2....序列關于這樣的先決條件構成一個圖,其中如果Ti必須要先于Tj完成,那么<Ti,Tj>就是該圖中的一條路徑,路徑長度為1的就是一條邊。 拓撲排序就是把這些任務按照完成的先后順序排列出來。顯然,這樣的順序可能不是唯一的,比如Tk,T...  閱讀全文
    posted @ 2007-12-14 21:00 DoubleH 閱讀(6416) | 評論 (1)編輯 收藏

         摘要: 很早就想總結一下了,一直沒有時間,OK,進入正題。 一 圖的基本概念及存儲結構 圖G是由頂點的有窮集合,以及頂點之間的關系組成,頂點的集合記為V,頂點之間的關系構成邊的集合E G=(V,E). 說一條邊從v1,連接到v2,那么有v1Ev2(E是V上的一個關系)《=》<v1,v2>∈E. 圖有有向圖,無向圖之分,無向圖的一條邊相當于有向圖的中兩條邊,即如果無向圖...  閱讀全文
    posted @ 2007-12-14 14:46 DoubleH 閱讀(4654) | 評論 (1)編輯 收藏

         摘要: 六 歸并排序 算法思想是每次把待排序列分成兩部分,分別對這兩部分遞歸地用歸并排序,完成后把這兩個子部分合并成一個 序列。 歸并排序借助一個全局性臨時數組來方便對子序列的歸并,該算法核心在于歸并。 Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.c...  閱讀全文
    posted @ 2007-12-14 01:03 DoubleH 閱讀(15412) | 評論 (11)編輯 收藏

    為了便于管理,先引入個基礎類:
    package algorithms;

    /**
     * 
    @author yovn
     *
     
    */
    public abstract class Sorter<extends Comparable<E>> {
        
        
    public abstract void sort(E[] array,int from ,int len);
        
        
    public final void sort(E[] array)
        {
            sort(array,
    0,array.length);
        }
        
    protected final void swap(E[] array,int from ,int to)
        {
            E tmp
    =array[from];
            array[from]
    =array[to];
            array[to]
    =tmp;
        }

    }
    一 插入排序
    該算法在數據規模小的時候十分高效,該算法每次插入第K+1到前K個有序數組中一個合適位置,K從0開始到N-1,從而完成排序:
    package algorithms;
    /**
     * 
    @author yovn
     
    */
    public class InsertSorter<extends Comparable<E>> extends Sorter<E> {

        
    /* (non-Javadoc)
         * @see algorithms.Sorter#sort(E[], int, int)
         
    */
        
    public void sort(E[] array, int from, int len) {
             E tmp
    =null;
              
    for(int i=from+1;i<from+len;i++)
              {
                  tmp
    =array[i];
                  
    int j=i;
                  
    for(;j>from;j--)
                  {
                      
    if(tmp.compareTo(array[j-1])<0)
                      {
                          array[j]
    =array[j-1];
                      }
                      
    else break;
                  }
                  array[j]
    =tmp;
              }
        }
            
        

    }

    二 冒泡排序
    這可能是最簡單的排序算法了,算法思想是每次從數組末端開始比較相鄰兩元素,把第i小的冒泡到數組的第i個位置。i從0一直到N-1從而完成排序。(當然也可以從數組開始端開始比較相鄰兩元素,把第i大的冒泡到數組的第N-i個位置。i從0一直到N-1從而完成排序。)

    package algorithms;

    /**
     * 
    @author yovn
     *
     
    */
    public class BubbleSorter<extends Comparable<E>> extends Sorter<E> {

        
    private static  boolean DWON=true;
        
        
    public final void bubble_down(E[] array, int from, int len)
        {
            
    for(int i=from;i<from+len;i++)
            {
                
    for(int j=from+len-1;j>i;j--)
                {
                    
    if(array[j].compareTo(array[j-1])<0)
                    {
                        swap(array,j
    -1,j);
                    }
                }
            }
        }
        
        
    public final void bubble_up(E[] array, int from, int len)
        {
            
    for(int i=from+len-1;i>=from;i--)
            {
                
    for(int j=from;j<i;j++)
                {
                    
    if(array[j].compareTo(array[j+1])>0)
                    {
                        swap(array,j,j
    +1);
                    }
                }
            }
        }
        @Override
        
    public void sort(E[] array, int from, int len) {
            
            
    if(DWON)
            {
                bubble_down(array,from,len);
            }
            
    else
            {
                bubble_up(array,from,len);
            }
        }
        
    }

    三,選擇排序
    選擇排序相對于冒泡來說,它不是每次發現逆序都交換,而是在找到全局第i小的時候記下該元素位置,最后跟第i個元素交換,從而保證數組最終的有序。
    相對與插入排序來說,選擇排序每次選出的都是全局第i小的,不會調整前i個元素了。
    package algorithms;
    /**
     * 
    @author yovn
     *
     
    */
    public class SelectSorter<extends Comparable<E>> extends Sorter<E> {

        
    /* (non-Javadoc)
         * @see algorithms.Sorter#sort(E[], int, int)
         
    */
        @Override
        
    public void sort(E[] array, int from, int len) {
            
    for(int i=0;i<len;i++)
            {
                
    int smallest=i;
                
    int j=i+from;
                
    for(;j<from+len;j++)
                {
                    
    if(array[j].compareTo(array[smallest])<0)
                    {
                        smallest
    =j;
                    }
                }
                swap(array,i,smallest);
                       
            }

        }
     
    }
    四 Shell排序
    Shell排序可以理解為插入排序的變種,它充分利用了插入排序的兩個特點:
    1)當數據規模小的時候非常高效
    2)當給定數據已經有序時的時間代價為O(N)
    所以,Shell排序每次把數據分成若個小塊,來使用插入排序,而且之后在這若個小塊排好序的情況下把它們合成大一點的小塊,繼續使用插入排序,不停的合并小塊,知道最后成一個塊,并使用插入排序。

    這里每次分成若干小塊是通過“增量” 來控制的,開始時增量交大,接近N/2,從而使得分割出來接近N/2個小塊,逐漸的減小“增量“最終到減小到1。

    一直較好的增量序列是2^k-1,2^(k-1)-1,.....7,3,1,這樣可使Shell排序時間復雜度達到O(N^1.5)
    所以我在實現Shell排序的時候采用該增量序列
    package algorithms;

    /**
     * 
    @author yovn
     
    */
    public class ShellSorter<extends Comparable<E>> extends Sorter<E>  {

        
    /* (non-Javadoc)
         * Our delta value choose 2^k-1,2^(k-1)-1,.7,3,1.
         * complexity is O(n^1.5)
         * @see algorithms.Sorter#sort(E[], int, int)
         
    */
        @Override
        
    public void sort(E[] array, int from, int len) {
            
            
    //1.calculate  the first delta value;
            int value=1;
            
    while((value+1)*2<len)
            {
                value
    =(value+1)*2-1;
            
            }
        
            
    for(int delta=value;delta>=1;delta=(delta+1)/2-1)
            {
                
    for(int i=0;i<delta;i++)
                {
                    modify_insert_sort(array,from
    +i,len-i,delta);
                }
            }

        }
        
        
    private final  void modify_insert_sort(E[] array, int from, int len,int delta) {
              
    if(len<=1)return;
              E tmp
    =null;
              
    for(int i=from+delta;i<from+len;i+=delta)
              {
                  tmp
    =array[i];
                  
    int j=i;
                  
    for(;j>from;j-=delta)
                  {
                      
    if(tmp.compareTo(array[j-delta])<0)
                      {
                          array[j]
    =array[j-delta];
                      }
                      
    else break;
                  }
                  array[j]
    =tmp;
              }

        }
    }

    五 快速排序
    快速排序是目前使用可能最廣泛的排序算法了。
    一般分如下步驟:
    1)選擇一個樞紐元素(有很對選法,我的實現里采用去中間元素的簡單方法)
    2)使用該樞紐元素分割數組,使得比該元素小的元素在它的左邊,比它大的在右邊。并把樞紐元素放在合適的位置。
    3)根據樞紐元素最后確定的位置,把數組分成三部分,左邊的,右邊的,樞紐元素自己,對左邊的,右邊的分別遞歸調用快速排序算法即可。
    快速排序的核心在于分割算法,也可以說是最有技巧的部分。
    package algorithms;

    /**
     * 
    @author yovn
     *
     
    */
    public class QuickSorter<extends Comparable<E>> extends Sorter<E> {

        
    /* (non-Javadoc)
         * @see algorithms.Sorter#sort(E[], int, int)
         
    */
        @Override
        
    public void sort(E[] array, int from, int len) {
            q_sort(array,from,from
    +len-1);
        }

        
        
    private final void q_sort(E[] array, int from, int to) {
            
    if(to-from<1)return;
            
    int pivot=selectPivot(array,from,to);

            
            
            pivot
    =partion(array,from,to,pivot);
            
            q_sort(array,from,pivot
    -1);
            q_sort(array,pivot
    +1,to);
            
        }


        
    private int partion(E[] array, int from, int to, int pivot) {
            E tmp
    =array[pivot];
            array[pivot]
    =array[to];//now to's position is available
            
            
    while(from!=to)
            {
                
    while(from<to&&array[from].compareTo(tmp)<=0)from++;
                
    if(from<to)
                {
                    array[to]
    =array[from];//now from's position is available
                    to--;
                }
                
    while(from<to&&array[to].compareTo(tmp)>=0)to--;
                
    if(from<to)
                {
                    array[from]
    =array[to];//now to's position is available now 
                    from++;
                }
            }
            array[from]
    =tmp;
            
    return from;
        }


        
    private int selectPivot(E[] array, int from, int to) {
        
            
    return (from+to)/2;
        }

    }

    還有歸并排序,堆排序,桶式排序,基數排序,下次在歸納。

    posted @ 2007-12-13 01:08 DoubleH 閱讀(36712) | 評論 (15)編輯 收藏

    /**
     * 
     
    */

    import java.util.Stack;
    import java.util.Vector;

    /**
     * 
    @author yovn
     *
     
    */
    public class TreeDemo {
        
        
    static interface NodeVistor
        {
             
    <T> void visit(BinaryTreeNode<T> node);
        }
        
    static class BinaryTree<T>
        {
            BinaryTreeNode
    <T> root;
            
            
    public BinaryTree(BinaryTreeNode<T> root) {
                
    this.root=root;
            }

            
    //no recursion ,pre-order
            void NLRVisit(NodeVistor visitor)
            {
                BinaryTreeNode
    <T> pointer=root;
                Stack
    <BinaryTreeNode<T>> stack=new Stack<BinaryTreeNode<T>>();
                
    while(!stack.isEmpty()||pointer!=null)
                {
                    
    if(pointer!=null)
                    {
                        visitor.visit(pointer);
                        
    if(pointer.rightChild!=null)
                        {
                            stack.push(pointer.rightChild);
                        }
                        pointer
    =pointer.leftChild;
                    }
                    
    //go to right child
                    else
                    {
                        pointer
    =stack.pop();
                        
                    }
                }
            }
            
            
    //no recursion , in-order
            void LNRVisit(NodeVistor visitor)
            {
                BinaryTreeNode
    <T> pointer=root;
                Stack
    <BinaryTreeNode<T>> stack=new Stack<BinaryTreeNode<T>>();
                
    while(!stack.isEmpty()||pointer!=null)
                {
                    
    if(pointer!=null)
                    {
                        stack.push(pointer);
                        
                        pointer
    =pointer.leftChild;
                    }
                    
    //no left child here, then visit root and then go to right child
                    else
                    {
                        pointer
    =stack.pop();
                        visitor.visit(pointer);
                        pointer
    =pointer.rightChild;
                        
                    }
                }
            }
            
            
            
    //no recursion ,post-order,this one is the most complex one.
            
    //we need know from which side ,it back(left or right)
            void LRNVisit(NodeVistor visitor)
            {
                
    if(root==null)return;
                BinaryTreeNode
    <T> pointer=root;
                Stack
    <BinaryTreeNode<T>> stack=new Stack<BinaryTreeNode<T>>();
                
    while(true)
                {
                    
                    
    //mark left 
                    while(pointer!=null)
                    {
                        stack.push(pointer);
                        pointer
    =pointer.leftChild;
                    }
                    
                    
                    pointer
    =stack.pop();
                    
                    
    while(pointer.visitedRight)//back from right child, so we can visit it now.
                    {
                        visitor.visit(pointer);
                        
    if(stack.isEmpty())return;
                        pointer
    =stack.pop();
                    }
                
                    pointer.visitedRight
    =true;
                    stack.push(pointer);
                    
                    pointer
    =pointer.rightChild;
                    
                    
                }
                
            }
            
            
            
    void levelOrder(NodeVistor visitor)
            {
                
    if(root==null)return;
                BinaryTreeNode
    <T> pointer=root;
                Vector
    <BinaryTreeNode<T>> queue=new Vector<BinaryTreeNode<T>>();
                
                queue.add(pointer);
                
    while(!queue.isEmpty())
                {
                    BinaryTreeNode
    <T> node=queue.remove(0);
                    visitor.visit(node);
                    
    if(node.leftChild!=null)
                    {
                        queue.add(node.leftChild);
                    }
                    
    if(node.rightChild!=null)
                    {
                        queue.add(node.rightChild);
                    }
                    
                }
                
            }
            
        }
        
    static class BinaryTreeNode<T>
        {
            
            BinaryTreeNode(T data)
            {
                
    this.data=data;
            }
            T data;
            
    boolean visitedRight;
            BinaryTreeNode
    <T> leftChild;
            BinaryTreeNode
    <T> rightChild;
        }

        
    /**
         * 
         
    */
        
    public TreeDemo() {
            
    // TODO Auto-generated constructor stub
        }

        
    /**
         * 
    @param args
         
    */
        
    public static void main(String[] args) {
            BinaryTreeNode
    <String> root=new BinaryTreeNode<String>("A");
            root.leftChild
    =new BinaryTreeNode<String>("B");
            root.rightChild
    =new BinaryTreeNode<String>("C");
            
            
            root.leftChild.leftChild
    =new BinaryTreeNode<String>("D");
            
            root.rightChild.leftChild
    =new BinaryTreeNode<String>("E");
            
            root.rightChild.rightChild
    =new BinaryTreeNode<String>("F");
            
            root.rightChild.leftChild.rightChild
    =new BinaryTreeNode<String>("G");
            
            root.rightChild.rightChild.leftChild
    =new BinaryTreeNode<String>("H");
            root.rightChild.rightChild.rightChild
    =new BinaryTreeNode<String>("I");
            
            NodeVistor visitor
    =new NodeVistor()
            {

                @Override
                
    public <T> void visit(BinaryTreeNode<T> node) {
                    System.out.print(
    "'"+node.data+"'");
                    
                }
                
            };
            
            BinaryTree
    <String> tree=new BinaryTree<String>(root);

            
            System.out.println(
    "pre-order visit");
            tree.NLRVisit(visitor);
            System.out.println();
            System.out.println(
    "in-order visit");
            
            tree.LNRVisit(visitor);
            
            System.out.println();
            System.out.println(
    "post-order visit");
            
            tree.LRNVisit(visitor);
            
            System.out.println();
            System.out.println(
    "level-order visit");
            
            tree.levelOrder(visitor);
        }

    }
    posted @ 2007-10-11 16:05 DoubleH 閱讀(841) | 評論 (0)編輯 收藏

    /**
     * 
     
    */
    package com.yovn.algo;

    import java.util.Stack;
    import java.util.Vector;

    /**
     * 
    @author yovn
     *
     
    */
    public class Caculator {

        
        
    class Item
        {
            
    boolean ops;
            
    int value;
            
            Character opVal;
            
    int opPriority;
        }
        
        Stack
    <Item> opStack=new Stack<Item>();
        Vector
    <Item> calcStack=new Vector<Item>();
        
    /**
         * 
         
    */
        
    public Caculator() {
            
    // TODO Auto-generated constructor stub
        }
        
        
        
        
        
    public int calc()
        {
            Stack
    <Item> tmp=new Stack<Item>();
            
    while(!calcStack.isEmpty())
            {
                Item it
    =calcStack.remove(0);
                
                
    if(!it.ops)
                {
                    tmp.push(it);
                }
                
    else
                {
                    
    int op2=tmp.pop().value;
                    
    int op1=tmp.pop().value;
                    Item newItem
    =new Item();
                    newItem.ops
    =true;
                    
    switch(it.opVal)
                    {
                    
    case '+':
                        newItem.value
    =op1+op2;
                        
                        
    break;
                    
    case '-':
                        newItem.value
    =op1-op2;
                        
    break;
                    
    case '*':
                        
                        newItem.value
    =op1*op2;
                        
    break;
                    
    case '/':
                        newItem.value
    =op1/op2;
                        
    break;
                    }
                    tmp.push(newItem);
                }
            }
            
    return tmp.pop().value;
        }
        
    /**
         * 1)數字直接輸出
         * 2)開括號則壓棧
         * 3)閉括號把棧中元素依次輸出直到遇到開括號
         * 4)運算符時
         *     a)循環,當棧非空,并且棧頂元素不是開括號,并且棧頂運算符優先級不低于輸入的運算符的優先級,反復將其輸出
         *     b)把輸入運算符壓棧
         * 5)輸出棧內剩余元素
         * 
    @param in
         * 
    @return
         
    */
        
    public String transInfixToPosfix(String in)
        {
            
    char[] cin=in.toCharArray();
            StringBuffer buffer
    =new StringBuffer();
           
            
    for(int i=0;i<cin.length;i++)
            {
                Item newItem
    =new Item();
                newItem.opPriority
    =1;
                newItem.ops
    =false;
                
                
    switch(cin[i])
                {
                
                
    case '+':
                    newItem.opPriority
    =1;
                    newItem.ops
    =true;
                    newItem.opVal
    ='+';
                    doOps(buffer, newItem);
                    
                    
    break;
                
    case '-':
                    newItem.opPriority
    =1;
                    newItem.ops
    =true;
                    newItem.opVal
    ='-';
                    doOps(buffer, newItem);
                    
    break;
                
    case '*':
                    newItem.opPriority
    =2;
                    newItem.ops
    =true;
                    newItem.opVal
    ='*';
                    doOps(buffer, newItem);
                    
    break;
                
    case '/':
                    newItem.opPriority
    =2;
                    newItem.ops
    =true;
                    newItem.opVal
    ='/';
                    doOps(buffer, newItem);
                    
    break;
                    
                
    case '(':
                    newItem.ops
    =true;
                    newItem.opVal
    ='(';
                    opStack.push(newItem);
                    
                    
    break;
                
    case ')':
                    
    boolean meetClose=false;
                    
    while(!opStack.isEmpty())
                    {
                        Item item
    =opStack.peek();
                        
    if(item.ops&&item.opVal!='(')
                        {
                            calcStack.add(item);
                            opStack.pop();
                            buffer.append(item.opVal);
                        }
                        
    else if(item.ops)
                        {
                            opStack.pop();
                            meetClose
    =true;
                            
    break;
                        }
                    }
                    
    if(!meetClose)
                    {
                        
    throw new RuntimeException();
                    }
                    
    break;
                    
                
    default:
                    
    int j=i;
                    
    for(;j<cin.length&&cin[j]>='0'&&cin[j]<='9';j++);
                    
    if(j==i)
                    {
                        
    throw new RuntimeException("wrong input.");
                    }
                    newItem.ops
    =false;
                    newItem.value
    =Integer.parseInt(new String(cin,i,j-i));
                    buffer.append(newItem.value);
                    calcStack.add(newItem);
                    i
    =j-1;
                    
    break;
                    
                    
                }
            }
            
    while(!opStack.isEmpty())
            {
                Item item
    =opStack.pop();
                calcStack.add(item);
                buffer.append(item.opVal);
                
            }
            
    return buffer.toString();
            
        }



        
    private void doOps(StringBuffer buffer, Item newItem) {
            
    while(!opStack.isEmpty())
            {
                Item item
    =opStack.peek();
                
    if(item.opVal!='('&&item.opPriority>=newItem.opPriority)
                {
                    calcStack.add(item);
                    opStack.pop();
                    buffer.append(item.opVal);
                }
                
    else
                {
                    
    break;
                }
            }
            opStack.push(newItem);
        }
        

        
    /**
         * 
    @param args
         
    */
        
    public static void main(String[] args) {
            Caculator calc
    =new Caculator();
            
            System.out.println(
    "1+2*3+7-(4/2+8)/5="+calc.transInfixToPosfix("1+2*3+7-(4/2+8)/5"));
            System.out.println(
    "value is:"+calc.calc());

        }

    }
    posted @ 2007-10-09 22:48 DoubleH 閱讀(996) | 評論 (1)編輯 收藏

    算法:

    設G是帶權圖,圖中的頂點多于一個,且所有的權都為正數。本算法確定從頂點S到G中其他各個頂點的距離和最短通路。在本算法中P表示帶永久標記的頂點的集合。頂點A的前驅是P中的一個頂點,用來標記A。頂點U和V之間的邊的權重用W(U,V)表示,如果U和V之間沒有邊,則記作W(U,V)=∞.

    步驟1 (對S做標記)

          (a)將S標記為0,并使S沒有前驅

          (b)令P={S}

    步驟2 (對其他頂點作標記)

          將每個不在P中的頂點V標記為W(S,V)(可能是暫時的),并使V的前驅為S(可能是暫時的)

    步驟3 (擴大P,修改標記)

         Repeat

         步驟3.1 (是另一個標記永久化)

                      把不在P中且帶有最小標記的頂點U加入到P中去(如果這樣的頂點有多個則任選其中一個)

        步驟3.2  (修改臨時標記)

                    對每個不在P中并且和U相鄰的頂點X,把X的標記替換為下列這兩者中的較小者:i)X的舊標記,ii)U上的標記與W(U,X)之和。如果X的標記改變了,則使U成為X的新前驅(可能是暫時的)

        Until P包含G中的每一個頂點

    步驟4 (求出距離和最短通路)

       頂點Y上的標記是從S到Y的距離。如果Y上的標記是∞,那么從S到Y就沒有通路,從而

    沒有最短通路;否則,按照下列序列的逆序使用頂點就構成從S到Y的一條最短通路:

    Y,Y的前驅,Y的前驅的前驅,。。。。,直至S

     

     

    證明:Dijkstra算法給出了從S到G的各個頂點的最短通路長度。

     

    我們假設G中的每個頂點V都被賦予了一個標記L(V),它要么是一個數,要么是∞。假設P是G的頂點的集合,P包含S,滿足:

    1)如果V屬于P,則L(V)是從S到V的最短通路的長度,并且存在這樣的從S到V的最短通路:通路上的頂點都在P中

    2)如果V不屬于P,則L(V)是從S到V的滿足下面限制的最短通路的長度:V是通路中唯一一個不屬于P的頂點。

     

    我們可以用歸納法證明Dijkstra算法中的P符合上述定義的集合:

    1)當P中元素個數為1時,P對應算法中的第一步,P={S},顯然滿足。

    2)假設P中元素個數為K時,P滿足上述定義,下面看算法的的第三步,

       先找出不在P中且帶有最小標記的頂點U,標記為L(U), 可以證明從S到U的最短通路中除U外不包含不屬于P的元素。

    因為若存在除U外其他頂點,則最短通路為SP1P2...PnQ1Q2...QnU(P1,P2..Pn屬于P,Q1,Q2,...Qn不屬于P),則由性質2)最短通路長度為L(Q1)+PATH(Q1,U)>L(U)

    從而大于SP1P2..PnU的通路長度L(U),不是最短通路,所以從S到U的最短通路中除U外不包含不屬于P的元素,從而從S到U的最短通路長度由L(U)給出.

    現把U加入P中構成P' ,顯然P'滿足性質1)。

    取V不屬于P',顯然V也不屬于P,那么從S到V的最短通路且滿足除V外所有頂點都在P'中的通路有兩種可能,i)包含U,ii)不包含U。

    對i)SP1P2...PnUV=L(U)+W(U,V)

       ii)SP1P2..PnV=L(V)

    顯然二者中的最小給出了從S到V的最短通路且滿足除V外所有頂點都在P'中的長度。

    從而算法第三步給出的P'含K+1個元素且滿足1),2)。

    又歸納,命題得證!

     

    下面是一個Java版的實現:最短路徑的Java實現

    posted @ 2007-09-07 13:24 DoubleH 閱讀(6233) | 評論 (3)編輯 收藏

         摘要: 這周末看不進書了,于是完善了以前的Java轉EXE工具
    以前的工具運行時要把所有的class載入,這對于大點的項目是不合適的。
    這個版本調整了一下Loader的機制,保持EXE跟類文件渾然一體的同時又可以延遲加載class.
    另外這個版本的加密強度提高很多,用來代替那些class混淆軟件應該也不錯。:)  閱讀全文
    posted @ 2007-07-15 23:32 DoubleH 閱讀(2446) | 評論 (9)編輯 收藏

    僅列出標題
    共5頁: 上一頁 1 2 3 4 5 下一頁 
    主站蜘蛛池模板: 久久青草91免费观看| 免费少妇a级毛片人成网| 久久久久久亚洲精品无码| 亚洲精品第一国产综合境外资源| 日批视频网址免费观看| 亚洲影视自拍揄拍愉拍| 亚洲综合精品香蕉久久网| 精品香蕉在线观看免费| 三年片在线观看免费观看大全中国| 亚洲va在线va天堂va四虎| 国产免费无遮挡精品视频| 久久久久久AV无码免费网站| www亚洲精品久久久乳| 老色鬼久久亚洲AV综合| 亚洲成人一区二区| 免费在线看v网址| 一区二区三区无码视频免费福利 | 亚洲乱亚洲乱少妇无码| 亚洲人成免费电影| 国产精品视频全国免费观看| 亚洲中文字幕一二三四区苍井空| 久久九九亚洲精品| 免费又黄又硬又爽大片| 欧美a级在线现免费观看| 久久精品国产大片免费观看| 免费国产a理论片| 亚洲xxxx视频| 中文字幕亚洲第一在线| 国产亚洲精品成人a v小说| 日韩高清免费在线观看| 日韩欧毛片免费视频| 久久久久国产精品免费网站| www在线观看免费视频| 亚洲AV日韩AV一区二区三曲 | 在线观看免费无码专区| 九九全国免费视频| 久久久久亚洲精品无码网址色欲| 亚洲中文字幕人成乱码| 亚洲经典在线中文字幕| 亚洲AV日韩精品久久久久| 亚洲日韩欧洲无码av夜夜摸|