Advertisement
Guest User

Untitled

a guest
Jul 1st, 2015
179
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.76 KB | None | 0 0
  1. #include<ctime> // clock
  2. #include<iostream> // cout
  3. #include<fstream> // ofstream
  4. #include<algorithm> // swap
  5. #include<vector> // vector
  6.  
  7. using namespace std;
  8.  
  9. typedef unsigned uint;
  10.  
  11.  
  12. ////////////////////////////////////////////////////////////////////////////////
  13.  
  14. /// D-äres Heapsort ///
  15.  
  16. enum { D_MIN = 2, D_MAX = 16 };
  17.  
  18. //
  19. // Sei 'A[0..N-1]' die Arraydarstellung eines D-ären Heaps (linksvollständiger
  20. // D-ärer Baum mit Min-Heapordnung, dessen Knoten sind in 'A' in Levelorder-
  21. // Reihenfolge gespeichert) mit N Knoten und mit einer Fehlstelle am Knoten mit
  22. // Index 'p'. (d.h. verringert man den Schlüssel von 'A[p]' wird 'A' zum Heap).
  23. // Der Aufruf 'BubbleDown(A, N, p, D)' soll 'A' reparieren.
  24. //
  25. // Hinweis:
  26. // 1. Der Schlüssel des Elements 'A[i]' ist 'A[i].Key()'.
  27. // 2a. Schlüssel haben den Typ 'K',
  28. // 2b. zwei Schlüssel 'k0' und 'k1' können mit 'k0<k1', 'k0<=k1', 'k0>k1' und
  29. // 'k0>=k1' verglichen werden.
  30. // 3. Arrayeinträge haben den Typ 'T'.
  31. //
  32. // Für eine effiziente Implementierung:
  33. // 4. Vermeiden Sie den Schlüssel des selben Array-Elements mehrfach zu be-
  34. // rechnen (speichern Sie den Schlüssel in einer lokalen Variable.)
  35. // 5. Vermeiden Sie Einträge, von Vater- und Kindknoten stets zu tauschen, be-
  36. // nutzen Sie folgende Idee:
  37. // Sei A[i0]=a0, A[i1]=a1, ..., A[iM]=aM eine Sequenz der von 'BubbleDown' be-
  38. // arbeiteten (d.h. getauschten) Knoten vor der Bearbeitung.
  39. // Der Effekt von
  40. // swap(A[i0], A[i1]); swap(A[i1], A[i2]); ... swap(A[i(M-1)], A[iM]);
  41. // ist
  42. // A[i0]=a1, A[i1]=a2, ..., A[i(M-1)]=aM, A[iM]=a0.
  43. // Selbige Belegung kann durch eine Sequenz von Zuweisungen erzeugt werden:
  44. // T tmp=A[i0]; A[i0]=A[i1]; A[i2]=A[i3]; ... A[i(M-1)]=A[iM]; A[iM]=tmp;
  45. // Statt drei Zuweisungen (swap) benötigt man nur eine Zuweisung pro Array-
  46. // zelle zzgl. der Zuweisung von 'tmp'!
  47. //
  48. template<typename T>
  49. inline void BubbleDown(T A[], const uint N, uint p, const uint D)
  50. {
  51. typedef typename T::key_type K;
  52. /// TODO Anfang
  53.  
  54. uint minChild = p*D + 1;
  55. T temp = A[p];
  56. K tempKey = temp.Key();
  57. bool someChange = false;
  58.  
  59. while(p*D + 1 < N) {
  60. minChild = p*D + 1;
  61. for (uint i = p*D + 2; i <= p*D + D; i++) {//p * D + 1 + D - 1
  62. //Wenn N überschritten wird beenden
  63. if (i == N)
  64. break;
  65. //Wenn aktuelles Minimum größer =>neues Minimum
  66. if (A[minChild].Key() > A[i].Key()) {
  67. minChild = i;
  68. }
  69. }
  70.  
  71. if (tempKey >= A[minChild].Key()) {
  72. someChange = true;
  73. //temp = A[p];
  74. A[p] = A[minChild];
  75. //A[minChild] = temp;
  76.  
  77. p = minChild;
  78. }
  79. else break;
  80. }
  81. if(someChange)
  82. A[p] = temp;
  83.  
  84.  
  85.  
  86.  
  87. // bool tempFlag = false;
  88. // uint minChild = p*D + 1;
  89. // T temp = A[minChild];
  90. // uint minChildLast = p;
  91. //
  92. // while(minChild < N) {
  93. // for (uint i = p*D + 2; i <= p*D + 1 + D - 1; i++) {
  94. // //Wenn N überschritten wird beenden
  95. // if (i >= N)
  96. // break;
  97. // //Wenn aktuelles Minimum größer =>neues Minimum
  98. // if (A[minChild].Key() > A[i].Key()) {
  99. // minChild = i;
  100. // }
  101. // }
  102. //
  103. // if (A[p].Key() > A[minChild].Key()) {
  104. // if(!tempFlag) {
  105. // temp = A[p];
  106. // tempFlag = true;
  107. // }
  108. // A[p] = A[minChild];
  109. // //BubbleDown(A, N, minChild, D);
  110. // p = minChild;
  111. // minChild = p*D + 1;
  112. // minChildLast = minChild;
  113. // }
  114. // else break;
  115. // }
  116. //
  117. // A[minChildLast] = temp;
  118. /// TODO Ende
  119. }
  120.  
  121. //
  122. // Die Funktion 'MakeHeap(A, N, D)' arrangiert das Array 'A[0..N-1]' in einen
  123. // D-ären Min-Heap um (Heapaufbauphase).
  124. //
  125. // Hinweis:
  126. // 1. In der Heapaufbauphase ist der erste Knoten, an dem etwas zu tun ist, der
  127. // Vater vom Knoten mit Index N-1.
  128. // 2. Die Implementierung ist (fast) ein Einzeiler!
  129. //
  130. template<typename T>
  131. void MakeHeap(T A[], const uint N, const uint D)
  132. {
  133. /// TODO Anfang
  134.  
  135. for (int i = (N - 1) / D; i >= 0; i--) {
  136. BubbleDown(A, N, i, D);
  137. }
  138. /// TODO Ende
  139. }
  140.  
  141. //
  142. // Vorausgesetzt, das Array 'A[0..N-1]' ist ein D-ärer Min-Heap, sortiert die
  143. // Funktion 'HeapSelect(A, N, D)' das Array 'A' absteigend.
  144. //
  145. // Hinweis:
  146. // 1. Die Funktion 'swap(A[i], A[j])' tasucht die Elemente 'A[i]' und 'A[j]'.
  147. // 2. Die Implementierung ist (fast) ein Einzeiler!
  148. //
  149. template<typename T>
  150. void HeapSelect(T A[], const uint N, const uint D)
  151. {
  152. /// TODO Anfang
  153. for (int i = N - 1; i > 0; i--) {
  154. swap(A[i], A[0]);
  155. BubbleDown(A, i, 0, D);
  156. }
  157. /// TODO Ende
  158. }
  159.  
  160. //
  161. // Die Funktion 'DAryHeapSort(A, N, D)' sortiert das Array 'A[0..N-1]' mit
  162. // D-ärem Heapsort.
  163. //
  164. template<typename T>
  165. void DAryHeapSort(T A[], const uint N, const uint D)
  166. {
  167. MakeHeap(A, N, D); HeapSelect(A, N, D);
  168. }
  169.  
  170.  
  171. ////////////////////////////////////////////////////////////////////////////////
  172.  
  173. unsigned long long cmps;
  174. unsigned z;
  175.  
  176. template<uint M>
  177. struct key {
  178. int x;
  179. key() {}
  180. key(int y) : x(y) {}
  181. bool operator<=(const key& k) const { ++cmps; for (uint i = 0; i<M; z += z + i++); return x <= k.x; }
  182. bool operator>=(const key& k) const { ++cmps; for (uint i = 0; i<M; z += z + i++); return x >= k.x; }
  183. bool operator<(const key& k) const { ++cmps; for (uint i = 0; i<M; z += z + i++); return x<k.x; }
  184. bool operator>(const key& k) const { ++cmps; for (uint i = 0; i<M; z += z + i++); return x>k.x; }
  185. };
  186.  
  187. template<uint N = 1, uint M = 0>
  188. struct item {
  189. int x[N];
  190. item() {}
  191. item(const int y) { x[0] = y; }
  192. typedef key<M> key_type;
  193. key_type Key() const { return key<M>(x[0]); }
  194. };
  195.  
  196. void Test()
  197. {
  198. static const char x[] = { '|', '/', '-', '\\', '|', '/', '-', '\\' };
  199. clock_t t = 0;
  200. vector< item<1, 0> > A; A.reserve(1u << 20);
  201. vector<uint> c; c.reserve(A.capacity() / 10 + 1);
  202.  
  203. clock_t T = 60 * CLOCKS_PER_SEC + clock(); // 1 Minute
  204. for (uint i = 0;;) {
  205. A.resize(1 + (rand() % A.capacity()));
  206. c.resize(1 + A.size() / 10, 0);
  207. // Array generieren, Häufigkeiten zählen
  208. for (uint j = 0; j<A.size(); ++j) {
  209. const int x = rand() % ((A.size() + 9) / 10);
  210. A[j] = x; ++c[x];
  211. }
  212. // Sortieren
  213. DAryHeapSort(&A[0], A.size(), D_MIN + (rand() % (D_MAX - D_MIN + 1)));
  214. // Aufsteigend sortiert?
  215. --c[A[0].x[0]];
  216. for (uint j = 1; j<A.size(); ++j) {
  217. if (!(A[j].Key() <= A[j - 1].Key())) {
  218. cerr << "\rFehler: Die Ordnung der sortierten Ausgabe stimmt nicht.\n";
  219. exit(1);
  220. }
  221. --c[A[j].x[0]];
  222. }
  223. // Keine Elemente mehr/weniger?
  224. for (uint j = 0; j<c.size(); ++j) {
  225. if (c[j++] != 0) {
  226. cerr << "\rFehler: Die sortierte Ausgabe enthält duplizierte Schlüssel.\n";
  227. exit(1);
  228. }
  229. }
  230. // Mitteilung: Wir stecken in keiner Endlosschleife!
  231. if (clock() - t >= CLOCKS_PER_SEC / 8) {
  232. t = clock();
  233. if (t<T) {
  234. cout << "\rAbbrechen mit STRG+C. Teste... " << x[i & 7];
  235. }
  236. else {
  237. cout << "\rTest abgeschlossen. " << endl;
  238. return;
  239. }
  240. ++i;
  241. }
  242. }
  243. }
  244.  
  245. template<uint E>
  246. void ScanD()
  247. {
  248. enum { N = 1000000, R = 50, T = 10 };
  249. char file[] = { 'd', 'h', 's', 'c', '0' + E, '.', 't', 'x', 't', 0 };
  250. ofstream oc(file);
  251. file[3] = 't'; ofstream ot(file);
  252. // E=0: Objekte klein, Vergleich billig
  253. // E=1: Objekte groß, Vergleich billig
  254. // E=2: Objekte klein, Vergleich teuer
  255. vector< item< E == 1 ? 16 : 1, E == 2 ? 32 : 0> > A; A.resize(N);
  256. for (uint i = 0; i<A.size(); ++i) A[i] = i;
  257.  
  258. for (uint D = D_MIN; D <= D_MAX; ++D) {
  259. cmps = 0;
  260. clock_t t0 = clock(), dt;
  261. uint i = 0;
  262. while ((dt = clock() - t0)<T*CLOCKS_PER_SEC || i<R) {
  263. random_shuffle(A.begin(), A.end());
  264. DAryHeapSort(&A[0], A.size(), D);
  265. ++i;
  266. }
  267. cout << '.';
  268. oc << D << ' ' << double(cmps) / i << endl;
  269. ot << D << ' ' << double(dt) / i*(1.0 / CLOCKS_PER_SEC) << endl;
  270. }
  271. }
  272.  
  273. /// TODO Anfang Exp4
  274. enum { D = 3 }; // hier in Experiment 1 ermittelten Wert für D eintragen
  275. /// TODO Ende Exp4
  276.  
  277.  
  278. time_t seed = 0;
  279. int Rand(uint n) { return rand() % n; }
  280.  
  281.  
  282. template<uint P>
  283. void RunPhase()
  284. {
  285. enum { N = 100000, S = 5000, R = 50, T = 10 };
  286.  
  287. srand(seed == 0 ? seed = time(NULL) : seed); // RNG zurücksetzen
  288. char file[] = { 'd', 'h', 's', 'p', '0' + P, '.', 't', 'x', 't', 0 };
  289. ofstream out(file);
  290. vector< item<1, 0> > A; A.reserve(N);
  291.  
  292. for (uint n = S; n<A.capacity(); n += S) {
  293. A.resize(n);
  294. clock_t t0 = clock(), dt;
  295. uint i = 0;
  296. cmps = 0;
  297. while ((dt = clock() - t0)<T*CLOCKS_PER_SEC || i<R) {
  298. for (uint j = 0; j<A.size(); ++j) A[j] = j;
  299. random_shuffle(A.begin(), A.end(), Rand);
  300. switch (P) {
  301. case 0: MakeHeap(&A[0], A.size(), D); break;
  302. case 1: DAryHeapSort(&A[0], A.size(), D); break;
  303. default: break;
  304. }
  305. ++i;
  306. }
  307. out << n << ' ' << double(dt) / i*(1.0 / CLOCKS_PER_SEC) << endl;
  308. cout << '.';
  309. }
  310. }
  311.  
  312. void TimeMakeHeap()
  313. {
  314. RunPhase<0>(); RunPhase<1>(); RunPhase<2>();
  315. }
  316.  
  317. ////////////////////////////////////////////////////////////////////////////////
  318.  
  319. template<typename T, int N> int L(T(&A)[N]) { return N; }
  320.  
  321. static void(*Fn[])() = { Test, ScanD<0>, ScanD<1>, ScanD<2>, TimeMakeHeap };
  322.  
  323. int main(int argc, char* argv[])
  324. {
  325. if (argc != 2 || (argc == 2 && !('0' <= *argv[1] && *argv[1]<'0' + L(Fn)))) {
  326. cerr <<
  327. "Syntax: dhsort N\n"
  328. "Der obige Aufruf fuehrt Experiment N aus, dabei ist N eine natuerliche Zahl. Je\n"
  329. "nach Experiment werden unter Umstaenden Textdateien als Ausgabe erzeugt. Ver-\n"
  330. "fuegbare Experimente sind:\n"
  331. " 0 - D-aeres Heapsort wird auf verschiedenen, zufaellig generierten, Arrays ge-\n"
  332. " testet.\n"
  333. " 1 - D-aeres Heapsort wird fuer kleine Objekte mit schnellen Schluesselvergleichen\n"
  334. " auf uniform zufaellig gewaehlten Permutationen von {1, 2, ..., n}, fuer ver-\n"
  335. " schiedene n ausgefuehrt; Messung von: Vergleichsanzahl, Zeit.\n"
  336. " 2 - D-aeres Heapsort wird fuer grosse Objekte auf uniform zufaellig gewaehlten\n"
  337. " Permtationen von {1, 2, ..., n}, fuer verschiedene n, ausgefuehrt; Messung von\n"
  338. " Vergleichsanzahl, Zeit.\n"
  339. " 3 - D-aeres Heapsort wird fuer langsame Schluesselvergleiche auf uniform zufaellig\n"
  340. " gewaehlten Permtationen von {1, 2, ..., n}, fuer verschiedene n, ausgefuehrt;\n"
  341. " Messung von: Vergleichsanzahl, Zeit.\n"
  342. " 4 - D-aeres Heapsort wird fuer kleine Objekte mit schnellen Schluesselvergleichen\n"
  343. " auf uniform zufaellig gewaehlten Permutationen von {1, 2, ..., n}, fuer ein festes\n"
  344. " n, ausgeuehrt; Messung von: Vergleichsanzahl, Zeit für MakeHeap und HeapSelect.\n";
  345. return 1;
  346. }
  347.  
  348. const int i = *argv[1] - '0';
  349. cout << "Experiment " << i << " laeuft";
  350. Fn[i]();
  351. cout << endl;
  352. cin.get();
  353. return 0;
  354. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement