E81086713E446D36F62B2AA2A3502B5EB155

          Java雜家

          雜七雜八。。。一家之言

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

          #

          外部排序?qū)崿F(xiàn)使用堆來生成若干個順串,然后使用多路歸并算法來生成最終排序好的內(nèi)容。

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

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

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

          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 閱讀(3348) | 評論 (3)編輯 收藏

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

          有兩個比較經(jīng)典的算法是:
          1)Prim算法: 該算法的思想跟Dijstra算法非常相似,Dijstra算法中每次求出下一個頂點時依據(jù)的是離初始頂點最近的,而Prim算法則找離V1整個集合最近的,也就是從V1中某個節(jié)點出發(fā)到該頂點的邊的權(quán)值最小。
          其原理也是每次找局部最優(yōu),最后構(gòu)成全局最優(yōu)。
          實現(xiàn)如下

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

          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;
              }
              
          }


          從邊集里權(quán)最小的邊,我們又可以借助最小值堆來完成。有了父指針樹以及最小值堆,現(xiàn)實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,到此,圖論的大概的算法算是復(fù)習完了。

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

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

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

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

          為了便于管理,先引入個基礎(chǔ)類:
          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;
              }

          }
          一 插入排序
          該算法在數(shù)據(jù)規(guī)模小的時候十分高效,該算法每次插入第K+1到前K個有序數(shù)組中一個合適位置,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;
                    }
              }
                  
              

          }

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

          三,選擇排序
          選擇排序相對于冒泡來說,它不是每次發(fā)現(xiàn)逆序都交換,而是在找到全局第i小的時候記下該元素位置,最后跟第i個元素交換,從而保證數(shù)組最終的有序。
          相對與插入排序來說,選擇排序每次選出的都是全局第i小的,不會調(diào)整前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)當數(shù)據(jù)規(guī)模小的時候非常高效
          2)當給定數(shù)據(jù)已經(jīng)有序時的時間代價為O(N)
          所以,Shell排序每次把數(shù)據(jù)分成若個小塊,來使用插入排序,而且之后在這若個小塊排好序的情況下把它們合成大一點的小塊,繼續(xù)使用插入排序,不停的合并小塊,知道最后成一個塊,并使用插入排序。

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

          一直較好的增量序列是2^k-1,2^(k-1)-1,.....7,3,1,這樣可使Shell排序時間復(fù)雜度達到O(N^1.5)
          所以我在實現(xiàn)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)選擇一個樞紐元素(有很對選法,我的實現(xiàn)里采用去中間元素的簡單方法)
          2)使用該樞紐元素分割數(shù)組,使得比該元素小的元素在它的左邊,比它大的在右邊。并把樞紐元素放在合適的位置。
          3)根據(jù)樞紐元素最后確定的位置,把數(shù)組分成三部分,左邊的,右邊的,樞紐元素自己,對左邊的,右邊的分別遞歸調(diào)用快速排序算法即可。
          快速排序的核心在于分割算法,也可以說是最有技巧的部分。
          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;
              }

          }

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

          posted @ 2007-12-13 01:08 DoubleH 閱讀(36720) | 評論 (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 閱讀(847) | 評論 (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)數(shù)字直接輸出
               * 2)開括號則壓棧
               * 3)閉括號把棧中元素依次輸出直到遇到開括號
               * 4)運算符時
               *     a)循環(huán),當棧非空,并且棧頂元素不是開括號,并且棧頂運算符優(yōu)先級不低于輸入的運算符的優(yōu)先級,反復(fù)將其輸出
               *     b)把輸入運算符壓棧
               * 5)輸出棧內(nèi)剩余元素
               * 
          @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 閱讀(999) | 評論 (1)編輯 收藏

          算法:

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

          步驟1 (對S做標記)

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

                (b)令P={S}

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

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

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

               Repeat

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

                            把不在P中且?guī)в凶钚擞浀捻旤cU加入到P中去(如果這樣的頂點有多個則任選其中一個)

              步驟3.2  (修改臨時標記)

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

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

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

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

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

          Y,Y的前驅(qū),Y的前驅(qū)的前驅(qū),。。。。,直至S

           

           

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

           

          我們假設(shè)G中的每個頂點V都被賦予了一個標記L(V),它要么是一個數(shù),要么是∞。假設(shè)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中元素個數(shù)為1時,P對應(yīng)算法中的第一步,P={S},顯然滿足。

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

             先找出不在P中且?guī)в凶钚擞浀捻旤cU,標記為L(U), 可以證明從S到U的最短通路中除U外不包含不屬于P的元素。

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

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

          現(xiàn)把U加入P中構(gòu)成P' ,顯然P'滿足性質(zhì)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版的實現(xiàn):最短路徑的Java實現(xiàn)

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

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

          僅列出標題
          共5頁: 上一頁 1 2 3 4 5 下一頁 
          主站蜘蛛池模板: 南阳市| 安乡县| 东城区| 镇远县| 巨野县| 方正县| 曲沃县| 德阳市| 定日县| 苏尼特右旗| 宝山区| 杭锦旗| 佳木斯市| 偃师市| 连云港市| 黄浦区| 内丘县| 马关县| 大竹县| 保山市| 兴安县| 成武县| 偏关县| 正蓝旗| 孟连| 忻城县| 正定县| 易门县| 彭州市| 昔阳县| 外汇| 奉节县| 监利县| 隆德县| 五原县| 泰和县| 治县。| 米脂县| 平凉市| 库尔勒市| 长子县|