1.line.cs
using System;
using System.Collections;public class Lines  
{
ArrayList                       LinesBuffer;
int                             LinesCount;
public event InputEvtHandler    InputEvt;
public Lines() 
{
LinesCount      = 0;
LinesBuffer = new ArrayList();
}
public int Append(ArrayList line)
{
int pos = LinesBuffer.Add( line ); LinesCount++; EventArgs eArgs = new EventArgs();
InputEvt( this, eArgs );
return pos;
}
public bool Delete(int pos)
{
if( pos >= LinesCount ) // Only delete existing Elements
{                                                                       
return false;
} LinesBuffer.RemoveAt( pos ); LinesCount--; return true;
}
/**
 * Insert a line at the given index, all Elements, starting at <pos> a 
 * shifted up.
 *
 * To append it is allowed to insert at position Lines::LinesCount.
 *
 * \warn Insertions after Lines::LinesCount fails and returns false.
 **/
public bool Insert(ArrayList line, int pos)
{
if( pos > LinesCount )  // Only inserting directly behind the 
{                       // last Element is allowed
return false;
} LinesBuffer.Insert( pos, line ); LinesCount++; return true;
}
public int Count()
{
return LinesCount;
}
public Object Get(int Pos)
{
return LinesBuffer[ Pos ];
}
public IEnumerator GetIterator()
{
return LinesBuffer.GetEnumerator();
}
public Object GetTail()
{
return LinesBuffer[ LinesCount - 1 ];
}
public int GetTailPos()
{
return LinesCount - 1;
}
};2.Input .csusing System;
using System.Collections;
using System.IO;public class Input 
{
/**
 *<label>stores</label>
 */
Lines rawData;
ArrayList line;
ArrayList lines = new ArrayList(); internal Input(Lines rawData) 
{
this.rawData = rawData;
} private void ReadData() //从文件中读取数据
{
String fileName = System.Console.ReadLine();
StreamReader sr = File.OpenText(fileName);//打开文本文件
String input;
while ((input = sr.ReadLine()) != null) 
{
line = Tokenize(input);
lines.Add(line);
}
sr.Close();
} private String Append(String s, char c) 
{
if (s.Equals(String.Empty)) return c.ToString();
else return String.Concat(s, c.ToString());
} private ArrayList Tokenize(String s) 
{
int ret;
String word = String.Empty;
StringReader sr = new StringReader(s);
ArrayList tokens = new ArrayList(); do 
{
ret = sr.Read();
char c = (char)ret;
if (!(Char.IsWhiteSpace(c) || ret == -1)) word = Append(word, c);
else 
{
tokens.Add(word);
word = String.Empty;
}
} while (ret != -1); return tokens;
} public void Start() 
{
ReadData(); IEnumerator lineIterator = lines.GetEnumerator(); while (lineIterator.MoveNext()) 
{
ArrayList line = (ArrayList)lineIterator.Current;
rawData.Append(line);
}
}
}
3.CircularShift .cs
using System;
using System.Collections;public class CircularShift 
{ public event CircularShiftEvtHandler CircularShiftEvt;
private Lines rawData; public CircularShift(Lines lines) 
{
rawData = lines;
} public void OnInputEvt(object sender, EventArgs e) 
{ ArrayList newline = (ArrayList)rawData.GetTail(); for (int i = 0; i < newline.Count; i++) 
{
ArrayList temp = new ArrayList();
int j = 0;  int k = i; while (j < newline.Count) 
{
temp.Add(newline[k]);
k = ++k % newline.Count;
j++;
} CircularShiftEventArgs CirShEvArg = new CircularShiftEventArgs(temp);
CircularShiftEvt(this, CirShEvArg);
}
}
}
4.CircularShiftEventArgs.cs
using System;
using System.Collections;public class CircularShiftEventArgs : EventArgs
{
//
// constructor which copies "line" to internal member "l"
//
public CircularShiftEventArgs(ArrayList line)
{
l = new ArrayList(line);
} public ArrayList GetLine()
{
return l;
} private ArrayList l;
5.Alphabetizer.csusing System;
using System.Collections;//
// used for comparing two ArrayLists assuming the arrays hold strings
// (the ArrayList can be thought of lines of words)
//
class LineComparer: IComparer
{
public LineComparer(bool caseSensitive)
{
compareCaseSensitive = caseSensitive;
} public int Compare(object x, object y)
{
int lenx, leny, min;    // length of each ArrayList and min of both
int i, result;          // intermediate result of comparing two string/words
String a, b;            // for comparing two words lenx = ((ArrayList)x).Count;
leny = ((ArrayList)y).Count;
                        
// treat empty lines
if(lenx==0 && leny==0) return 0;        // equal (both empty)
if(lenx==0 && leny!=0) return -1;       // x smaller
if(lenx!=0 && leny==0) return 1;        // x greater
                        
// minimum of both so we know how much words can be compared
min = (lenx<leny)?lenx:leny;
                        
// compare words until one unequal is found
for(i=0; i<min; ++i)
{
// get words
a = (String) ((ArrayList) x)[i];
b = (String) ((ArrayList) y)[i];
                                
// compare words
result = String.Compare(a, b, compareCaseSensitive); // different?
if(result!=0) return result;
} // if we got here all words were equal but length may be different
// so decide depending on the size
                        
if(lenx==leny) return 0;        // completely the same
if(lenx>leny) return 1;         // line x longer => line x larger
return -1;                      // lenx < leny => line x shorter
} private bool compareCaseSensitive;
}
        
        
//
// class sorting incoming new lines into a "Lines"-Container
//
public class Alphabetizer
{ //
// constructor which receives a "Lines" object where
// new lines are inserted
//
public Alphabetizer(Lines lines)
{
permData = lines;
comparer = new LineComparer(true);
} //
// function which is called through
// delegate when new line arrived
//
public void OnCircularShiftEvt(object sender, CircularShiftEventArgs e)
{
ArrayList newline;
                
// get new line
newline = e.GetLine(); // if no words in line, stop
if(newline.Count == 0) return; InsertSorted(permData, newline, false);
} //
// insert the line, given by the words in "newline" into "lines"
//
private void InsertSorted(Lines lines, ArrayList newLine, bool insertDuplicates)
{
int number; number = lines.Count();
if(number==0)
{
lines.Insert(newLine, 0); // easy :)
return;
} // binary search to the right place
// if equal line found do nothing
// else insert line there
int low=0, mid, high=number-1, res;
while(low<=high)
{
mid = (low+high)/2; res = comparer.Compare(newLine, lines.Get(mid));
                        
if(res < 0)
{
// newLine smaller
high = mid-1;
}
else if(res > 0)
{
// newLine greater
low = mid+1;
}
else
{
// equal found
if(insertDuplicates)
{
// insert after the found duplicate
lines.Insert(newLine, mid+1);
}
return;
}
} // while // no duplicate was found => we are at the right place to insert
// insert at place "low" because low got greater than "high"
// and inserting puts the line before the adressed one
lines.Insert(newLine, low);
} private Lines permData;         
private LineComparer comparer;  
}