[838]外排序通用版
前段时间写了一个外排序的程序,但不够通用,这次完善了一下,改成通用的了
就不多介绍了,直接上码
<!--
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
--> 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.IO;
6
7 namespace Cn.Edu.Dlut.Wisdom.Algorithm
8 {
9 public class DiskSort<T> where T:IComparable<T>
10 {
11 /// <summary>
12 /// 工作目录
13 /// </summary>
14 private string workDir;
15 /// <summary>
16 /// 外排序的文件名
17 /// </summary>
18 private string fileName;
19 /// <summary>
20 /// 数据属性分割符
21 /// </summary>
22 private char[] sep;
23 /// <summary>
24 /// 排序依赖的属性序号,从0开始
25 /// </summary>
26 private int keyIndex;
27 /// <summary>
28 /// 最小文件分割大小
29 /// </summary>
30 private long minSliptSize;
31
32
33 /// <summary>
34 /// 构造函数/
35 /// </summary>
36 /// <param name="workDir">工作目录</param>
37 /// <param name="fileName">排序的文件名</param>
38 /// <param name="sep">属性分隔符</param>
39 /// <param name="keyIndex">排序属性序号</param>
40 /// <param name="sortType">排序属性类型</param>
41 /// <param name="minSliptSize">最小文件分割大小</param>
42 public DiskSort(string workDir, string fileName, char[] sep, int keyIndex, long minSliptSize)
43 {
44 this.workDir = workDir;
45 this.fileName = fileName;
46 this.sep = sep;
47 this.keyIndex = keyIndex;
48 this.minSliptSize = minSliptSize;
49 }
50
51 public void Sort()
52 {
53 MergeSort(fileName);
54 }
55
56 private void MergeSort(string fileName)
57 {
58 if (new FileInfo(workDir + fileName).Length <= minSliptSize) // 内存排序
59 {
60 var lines = File.ReadLines(workDir + fileName);
61 List<Pair<T>> pairs = new List<Pair<T>>();
62 foreach (string line in lines)
63 {
64 string[] ls = line.Split(sep);
65 T key = (T)ConvertString.ToType(typeof(T), ls[keyIndex]);
66 pairs.Add(new Pair<T>(key, line));
67 }
68 pairs.Sort();
69 using (StreamWriter sw = new StreamWriter(workDir + fileName))
70 {
71 foreach (Pair<T> p in pairs)
72 {
73 sw.WriteLine(p);
74 }
75 sw.Flush();
76 }
77 }
78 else // 硬盘排序
79 {
80 // 分解文件
81 string file1 = fileName + "1";
82 string file2 = fileName + "2";
83 using (StreamReader sr = new StreamReader(workDir + fileName))
84 using (StreamWriter sw1 = new StreamWriter(workDir + file1))
85 using (StreamWriter sw2 = new StreamWriter(workDir + file2))
86 {
87 int i = 0;
88 while (!sr.EndOfStream)
89 {
90 string line = sr.ReadLine();
91 if (i++ % 2 == 0)
92 sw1.WriteLine(line);
93 else
94 sw2.WriteLine(line);
95 }
96 sw1.Flush();
97 sw2.Flush();
98 }
99 // 对分解出的文件,分别进行排序
100 MergeSort(file1);
101 MergeSort(file2);
102 // 把两个文件进行合并
103 using (StreamReader sr1 = new StreamReader(workDir + file1))
104 using (StreamReader sr2 = new StreamReader(workDir + file2))
105 using (StreamWriter sw = new StreamWriter(workDir + fileName))
106 {
107 string line1 = sr1.ReadLine();
108 T key1 = (T)ConvertString.ToType(typeof(T), line1.Split(sep)[keyIndex]);
109 string line2 = sr2.ReadLine();
110 T key2 = (T)ConvertString.ToType(typeof(T), line2.Split(sep)[keyIndex]);
111 while (!sr1.EndOfStream || !sr2.EndOfStream)
112 {
113
114 if (key1.CompareTo(key2) <= 0)
115 {
116 sw.WriteLine(line1);
117 if (sr1.EndOfStream)
118 {
119 sw.WriteLine(line2);
120 while (!sr2.EndOfStream)
121 {
122 sw.WriteLine(sr2.ReadLine());
123 }
124 }
125 else
126 {
127 line1 = sr1.ReadLine();
128 key1 = (T)ConvertString.ToType(typeof(T), line1.Split(sep)[keyIndex]);
129 if (sr1.EndOfStream && sr2.EndOfStream)
130 {
131 if (key1.CompareTo(key2) <= 0)
132 {
133 sw.WriteLine(line1);
134 sw.WriteLine(line2);
135 }
136 else
137 {
138 sw.WriteLine(line2);
139 sw.WriteLine(line1);
140 }
141 }
142 }
143 }
144 else
145 {
146 sw.WriteLine(line2);
147 if (sr2.EndOfStream)
148 {
149 sw.WriteLine(line1);
150 while (!sr1.EndOfStream)
151 {
152 sw.WriteLine(sr1.ReadLine());
153 }
154 }
155 else
156 {
157 line2 = sr2.ReadLine();
158 key2 = (T)ConvertString.ToType(typeof(T), line2.Split(sep)[keyIndex]);
159 if (sr1.EndOfStream && sr2.EndOfStream)
160 {
161 if (key1.CompareTo(key2) <= 0)
162 {
163 sw.WriteLine(line1);
164 sw.WriteLine(line2);
165 }
166 else
167 {
168 sw.WriteLine(line2);
169 sw.WriteLine(line1);
170 }
171 }
172 }
173 }
174 }
175 sw.Flush();
176 }
177 // 删除临时文件
178 File.Delete(workDir + file1);
179 File.Delete(workDir + file2);
180 }
181 }
182 }
183
184 public class Pair<T>:IComparable<Pair<T>> where T:IComparable<T>
185 {
186 /// <summary>
187 /// 建值
188 /// </summary>
189 private T key;
190 /// <summary>
191 /// 字符串值
192 /// </summary>
193 private string all;
194
195 public Pair(T key, string all)
196 {
197 this.key = key;
198 this.all = all;
199 }
200
201 /// <summary>
202 /// 根据关键字进行比较
203 /// </summary>
204 /// <param name="other"></param>
205 /// <returns></returns>
206 public int CompareTo(Pair<T> other)
207 {
208 return key.CompareTo(other.key);
209 }
210
211 public override string ToString()
212 {
213 return all;
214 }
215 }
216
217 public class ConvertString
218 {
219 public static object ToType(Type type, string value)
220 {
221 return System.ComponentModel.TypeDescriptor.GetConverter(type).ConvertFrom(value);
222 }
223 }
224 }
225
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
--> 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.IO;
6
7 namespace Cn.Edu.Dlut.Wisdom.Algorithm
8 {
9 public class DiskSort<T> where T:IComparable<T>
10 {
11 /// <summary>
12 /// 工作目录
13 /// </summary>
14 private string workDir;
15 /// <summary>
16 /// 外排序的文件名
17 /// </summary>
18 private string fileName;
19 /// <summary>
20 /// 数据属性分割符
21 /// </summary>
22 private char[] sep;
23 /// <summary>
24 /// 排序依赖的属性序号,从0开始
25 /// </summary>
26 private int keyIndex;
27 /// <summary>
28 /// 最小文件分割大小
29 /// </summary>
30 private long minSliptSize;
31
32
33 /// <summary>
34 /// 构造函数/
35 /// </summary>
36 /// <param name="workDir">工作目录</param>
37 /// <param name="fileName">排序的文件名</param>
38 /// <param name="sep">属性分隔符</param>
39 /// <param name="keyIndex">排序属性序号</param>
40 /// <param name="sortType">排序属性类型</param>
41 /// <param name="minSliptSize">最小文件分割大小</param>
42 public DiskSort(string workDir, string fileName, char[] sep, int keyIndex, long minSliptSize)
43 {
44 this.workDir = workDir;
45 this.fileName = fileName;
46 this.sep = sep;
47 this.keyIndex = keyIndex;
48 this.minSliptSize = minSliptSize;
49 }
50
51 public void Sort()
52 {
53 MergeSort(fileName);
54 }
55
56 private void MergeSort(string fileName)
57 {
58 if (new FileInfo(workDir + fileName).Length <= minSliptSize) // 内存排序
59 {
60 var lines = File.ReadLines(workDir + fileName);
61 List<Pair<T>> pairs = new List<Pair<T>>();
62 foreach (string line in lines)
63 {
64 string[] ls = line.Split(sep);
65 T key = (T)ConvertString.ToType(typeof(T), ls[keyIndex]);
66 pairs.Add(new Pair<T>(key, line));
67 }
68 pairs.Sort();
69 using (StreamWriter sw = new StreamWriter(workDir + fileName))
70 {
71 foreach (Pair<T> p in pairs)
72 {
73 sw.WriteLine(p);
74 }
75 sw.Flush();
76 }
77 }
78 else // 硬盘排序
79 {
80 // 分解文件
81 string file1 = fileName + "1";
82 string file2 = fileName + "2";
83 using (StreamReader sr = new StreamReader(workDir + fileName))
84 using (StreamWriter sw1 = new StreamWriter(workDir + file1))
85 using (StreamWriter sw2 = new StreamWriter(workDir + file2))
86 {
87 int i = 0;
88 while (!sr.EndOfStream)
89 {
90 string line = sr.ReadLine();
91 if (i++ % 2 == 0)
92 sw1.WriteLine(line);
93 else
94 sw2.WriteLine(line);
95 }
96 sw1.Flush();
97 sw2.Flush();
98 }
99 // 对分解出的文件,分别进行排序
100 MergeSort(file1);
101 MergeSort(file2);
102 // 把两个文件进行合并
103 using (StreamReader sr1 = new StreamReader(workDir + file1))
104 using (StreamReader sr2 = new StreamReader(workDir + file2))
105 using (StreamWriter sw = new StreamWriter(workDir + fileName))
106 {
107 string line1 = sr1.ReadLine();
108 T key1 = (T)ConvertString.ToType(typeof(T), line1.Split(sep)[keyIndex]);
109 string line2 = sr2.ReadLine();
110 T key2 = (T)ConvertString.ToType(typeof(T), line2.Split(sep)[keyIndex]);
111 while (!sr1.EndOfStream || !sr2.EndOfStream)
112 {
113
114 if (key1.CompareTo(key2) <= 0)
115 {
116 sw.WriteLine(line1);
117 if (sr1.EndOfStream)
118 {
119 sw.WriteLine(line2);
120 while (!sr2.EndOfStream)
121 {
122 sw.WriteLine(sr2.ReadLine());
123 }
124 }
125 else
126 {
127 line1 = sr1.ReadLine();
128 key1 = (T)ConvertString.ToType(typeof(T), line1.Split(sep)[keyIndex]);
129 if (sr1.EndOfStream && sr2.EndOfStream)
130 {
131 if (key1.CompareTo(key2) <= 0)
132 {
133 sw.WriteLine(line1);
134 sw.WriteLine(line2);
135 }
136 else
137 {
138 sw.WriteLine(line2);
139 sw.WriteLine(line1);
140 }
141 }
142 }
143 }
144 else
145 {
146 sw.WriteLine(line2);
147 if (sr2.EndOfStream)
148 {
149 sw.WriteLine(line1);
150 while (!sr1.EndOfStream)
151 {
152 sw.WriteLine(sr1.ReadLine());
153 }
154 }
155 else
156 {
157 line2 = sr2.ReadLine();
158 key2 = (T)ConvertString.ToType(typeof(T), line2.Split(sep)[keyIndex]);
159 if (sr1.EndOfStream && sr2.EndOfStream)
160 {
161 if (key1.CompareTo(key2) <= 0)
162 {
163 sw.WriteLine(line1);
164 sw.WriteLine(line2);
165 }
166 else
167 {
168 sw.WriteLine(line2);
169 sw.WriteLine(line1);
170 }
171 }
172 }
173 }
174 }
175 sw.Flush();
176 }
177 // 删除临时文件
178 File.Delete(workDir + file1);
179 File.Delete(workDir + file2);
180 }
181 }
182 }
183
184 public class Pair<T>:IComparable<Pair<T>> where T:IComparable<T>
185 {
186 /// <summary>
187 /// 建值
188 /// </summary>
189 private T key;
190 /// <summary>
191 /// 字符串值
192 /// </summary>
193 private string all;
194
195 public Pair(T key, string all)
196 {
197 this.key = key;
198 this.all = all;
199 }
200
201 /// <summary>
202 /// 根据关键字进行比较
203 /// </summary>
204 /// <param name="other"></param>
205 /// <returns></returns>
206 public int CompareTo(Pair<T> other)
207 {
208 return key.CompareTo(other.key);
209 }
210
211 public override string ToString()
212 {
213 return all;
214 }
215 }
216
217 public class ConvertString
218 {
219 public static object ToType(Type type, string value)
220 {
221 return System.ComponentModel.TypeDescriptor.GetConverter(type).ConvertFrom(value);
222 }
223 }
224 }
225

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名小橋流水(包含链接)。如您有任何疑问或者授权方面的协商,请给我发邮件。