1 24 25 package com.mckoi.util; 26 27 import java.util.ArrayList ; 28 29 64 65 public abstract class AbstractBlockIntegerList 66 implements IntegerListInterface { 67 68 74 78 protected ArrayList block_list = new ArrayList (10); 79 80 83 private int count; 84 85 90 94 private boolean immutable; 95 96 97 100 public AbstractBlockIntegerList() { 101 immutable = false; 102 count = 0; 103 105 107 } 108 109 112 public AbstractBlockIntegerList(IntegerListBlockInterface[] blocks) { 113 this(); 114 for (int i = 0; i < blocks.length; ++i) { 115 block_list.add(blocks[i]); 116 count += blocks[i].size(); 117 } 118 } 119 120 123 public AbstractBlockIntegerList(IntegerVector ivec) { 124 this(); 125 126 int sz = ivec.size(); 127 for (int i = 0; i < sz; ++i) { 128 add(ivec.intAt(i)); 129 } 130 } 131 132 136 public AbstractBlockIntegerList(IntegerListInterface i_list) { 137 this(); 138 139 if (i_list instanceof AbstractBlockIntegerList) { 140 AbstractBlockIntegerList in_list = (AbstractBlockIntegerList) i_list; 142 143 145 ArrayList in_blocks = in_list.block_list; 146 int in_blocks_count = in_blocks.size(); 147 for (int i = 0; i < in_blocks_count; ++i) { 149 IntegerListBlockInterface block = 151 (IntegerListBlockInterface) in_blocks.get(i); 152 IntegerListBlockInterface dest_block = 154 insertListBlock(i, newListBlock()); 155 block.copyTo(dest_block); 157 } 158 159 count = i_list.size(); 162 } 163 else { 164 IntegerIterator i = i_list.iterator(); 166 while (i.hasNext()) { 167 add(i.next()); 168 } 169 } 170 171 if (i_list.isImmutable()) { 173 setImmutable(); 174 } 175 176 } 177 178 179 180 182 185 protected abstract IntegerListBlockInterface newListBlock(); 186 187 191 protected void deleteListBlock(IntegerListBlockInterface list_block) { 192 } 193 194 198 final void copyToArray(int[] array, int offset, int length) { 199 if (array.length >= length && (offset + length) <= size()) { 200 for (int i = 0; i < block_list.size() ; ++i) { 201 IntegerListBlockInterface block = 202 (IntegerListBlockInterface) block_list.get(i); 203 offset += block.copyTo(array, offset); 204 } 205 return; 206 } 207 throw new Error ("Size mismatch."); 208 } 209 210 211 214 private final IntegerListBlockInterface 215 insertListBlock(int index, IntegerListBlockInterface list_block) { 216 block_list.add(index, list_block); 217 218 if (index + 1 < block_list.size()) { 220 IntegerListBlockInterface next_b = 221 (IntegerListBlockInterface) block_list.get(index + 1); 222 list_block.next = next_b; 223 next_b.previous = list_block; 224 } 225 else { 226 list_block.next = null; 227 } 228 229 if (index > 0) { 231 IntegerListBlockInterface previous_b = 232 (IntegerListBlockInterface) block_list.get(index - 1); 233 list_block.previous = previous_b; 234 previous_b.next = list_block; 235 } 236 else { 237 list_block.previous = null; 238 } 239 240 return list_block; 241 } 242 243 247 private final void removeListBlock(int index) { 248 IntegerListBlockInterface new_prev = null; 250 IntegerListBlockInterface new_next = null; 251 if (index + 1 < block_list.size()) { 252 new_next = (IntegerListBlockInterface) block_list.get(index + 1); 253 } 254 if (index > 0) { 255 new_prev = (IntegerListBlockInterface) block_list.get(index - 1); 256 } 257 258 if (new_prev != null) { 259 new_prev.next = new_next; 260 } 261 if (new_next != null) { 262 new_next.previous = new_prev; 263 } 264 265 IntegerListBlockInterface been_removed = 266 (IntegerListBlockInterface) block_list.remove(index); 267 deleteListBlock(been_removed); 268 } 269 270 273 private final void insertIntoBlock(int val, int block_index, 274 IntegerListBlockInterface block, int position) { 275 block.insertIntAt(val, position); 276 ++count; 277 if (block.isFull()) { 279 282 int move_size = (block.size() / 7) - 1; 284 285 IntegerListBlockInterface move_to; 287 if (block_index < block_list.size() - 1) { 289 IntegerListBlockInterface next_b = 290 (IntegerListBlockInterface) block_list.get(block_index + 1); 291 if (next_b.canContain(move_size)) { 295 move_to = next_b; 296 } 297 else { 298 move_to = insertListBlock(block_index + 1, newListBlock()); 300 } 301 302 } 303 else { 304 move_to = insertListBlock(block_index + 1, newListBlock()); 306 } 307 308 block.moveTo(move_to, 0, move_size); 311 312 } 313 } 314 315 319 protected final int removeFromBlock(int block_index, 320 IntegerListBlockInterface block, 321 int position) { 322 int old_value = block.removeIntAt(position); 323 --count; 324 if (block.isEmpty() && block_list.size() > 1) { 327 removeListBlock(block_index); 328 } 329 330 return old_value; 331 } 332 333 338 private final int findBlockContaining(Object key, IndexComparator c) { 339 if (count == 0) { 340 return -1; 341 } 342 343 int low = 0; 344 int high = block_list.size() - 1; 345 346 while (low <= high) { 347 int mid = (low + high) / 2; 348 IntegerListBlockInterface block = 349 (IntegerListBlockInterface) block_list.get(mid); 350 351 if (c.compare(block.bottomInt(), key) > 0) { 353 high = mid - 1; 354 } 355 else if (c.compare(block.topInt(), key) < 0) { 357 low = mid + 1; 358 } 359 else { 361 return mid; 362 } 363 } 364 365 367 return -(low + 1); } 369 370 375 private final int findLastBlock(Object key, IndexComparator c) { 376 if (count == 0) { 377 return -1; 378 } 379 380 int low = 0; 381 int high = block_list.size() - 1; 382 383 while (low <= high) { 384 385 if (high - low <= 2) { 386 for (int i = high; i >= low; --i) { 387 IntegerListBlockInterface block = 388 (IntegerListBlockInterface) block_list.get(i); 389 if (c.compare(block.bottomInt(), key) <= 0) { 390 if (c.compare(block.topInt(), key) >= 0) { 391 return i; 392 } 393 else { 394 return -(i + 1) - 1; 395 } 396 } 397 } 398 return -(low + 1); 399 } 400 401 int mid = (low + high) / 2; 402 IntegerListBlockInterface block = 403 (IntegerListBlockInterface) block_list.get(mid); 404 405 if (c.compare(block.bottomInt(), key) > 0) { 407 high = mid - 1; 408 } 409 else if (c.compare(block.topInt(), key) < 0) { 411 low = mid + 1; 412 } 413 else { 415 low = mid; 416 if (low == high) { 417 return low; 418 } 419 } 420 } 421 422 return -(low + 1); } 424 425 430 private final int findFirstBlock(Object key, IndexComparator c) { 431 if (count == 0) { 432 return -1; 433 } 434 435 int low = 0; 436 int high = block_list.size() - 1; 437 438 while (low <= high) { 439 440 if (high - low <= 2) { 441 for (int i = low; i <= high; ++i) { 442 IntegerListBlockInterface block = 443 (IntegerListBlockInterface) block_list.get(i); 444 if (c.compare(block.topInt(), key) >= 0) { 445 if (c.compare(block.bottomInt(), key) <= 0) { 446 return i; 447 } 448 else { 449 return -(i + 1); 450 } 451 } 452 } 453 return -(high + 1) - 1; 454 } 455 456 int mid = (low + high) / 2; 457 IntegerListBlockInterface block = 458 (IntegerListBlockInterface) block_list.get(mid); 459 460 if (c.compare(block.bottomInt(), key) > 0) { 462 high = mid - 1; 463 } 464 else if (c.compare(block.topInt(), key) < 0) { 466 low = mid + 1; 467 } 468 else { 470 high = mid; 471 } 472 } 473 474 return -(low + 1); } 476 477 478 483 private final int findFirstBlock(int val) { 484 if (count == 0) { 485 return -1; 486 } 487 488 int low = 0; 489 int high = block_list.size() - 1; 490 491 while (low <= high) { 492 493 if (high - low <= 2) { 494 for (int i = low; i <= high; ++i) { 495 IntegerListBlockInterface block = 496 (IntegerListBlockInterface) block_list.get(i); 497 if (block.topInt() >= val) { 498 if (block.bottomInt() <= val) { 499 return i; 500 } 501 else { 502 return -(i + 1); 503 } 504 } 505 } 506 return -(high + 1) - 1; 507 } 508 509 int mid = (low + high) / 2; 510 IntegerListBlockInterface block = 511 (IntegerListBlockInterface) block_list.get(mid); 512 513 if (block.bottomInt() > val) { 515 high = mid - 1; 516 } 517 else if (block.topInt() < val) { 519 low = mid + 1; 520 } 521 else { 523 high = mid; 524 } 525 } 526 527 return -(low + 1); } 529 530 535 private final int findLastBlock(int val) { 536 if (count == 0) { 537 return -1; 538 } 539 540 int low = 0; 541 int high = block_list.size() - 1; 542 543 while (low <= high) { 544 545 if (high - low <= 2) { 546 for (int i = high; i >= low; --i) { 547 IntegerListBlockInterface block = 548 (IntegerListBlockInterface) block_list.get(i); 549 if (block.bottomInt() <= val) { 550 if (block.topInt() >= val) { 551 return i; 552 } 553 else { 554 return -(i + 1) - 1; 555 } 556 } 557 } 558 return -(low + 1); 559 } 560 561 int mid = (low + high) / 2; 562 IntegerListBlockInterface block = 563 (IntegerListBlockInterface) block_list.get(mid); 564 565 if (block.bottomInt() > val) { 567 high = mid - 1; 568 } 569 else if (block.topInt() < val) { 571 low = mid + 1; 572 } 573 else { 575 low = mid; 576 if (low == high) { 577 return low; 578 } 579 } 580 } 581 582 return -(low + 1); } 584 585 586 587 588 589 590 595 private void checkImmutable() { 596 if (immutable) { 597 throw new Error ("List is immutable."); 598 } 599 else if (block_list.size() == 0) { 603 insertListBlock(0, newListBlock()); 604 } 605 } 606 607 609 612 public final void setImmutable() { 613 immutable = true; 614 } 615 616 619 public final boolean isImmutable() { 620 return immutable; 621 } 622 623 624 627 630 public final int size() { 631 return count; 632 } 633 634 638 public final int get(int pos) { 639 int size = block_list.size(); 640 int start = 0; 641 for (int i = 0; i < size; ++i) { 642 IntegerListBlockInterface block = 643 (IntegerListBlockInterface) block_list.get(i); 644 int bsize = block.size(); 645 if (pos >= start && pos < start + bsize) { 646 return block.intAt(pos - start); 647 } 648 start += bsize; 649 } 650 throw new Error ("'pos' (" + pos + ") out of bounds."); 651 } 652 653 656 public final void add(int val, int pos) { 657 checkImmutable(); 658 659 int size = block_list.size(); 660 int start = 0; 661 for (int i = 0; i < size; ++i) { 662 Object ob = block_list.get(i); 663 IntegerListBlockInterface block = (IntegerListBlockInterface) ob; 664 int bsize = block.size(); 665 if (pos >= start && pos <= start + bsize) { 666 insertIntoBlock(val, i, block, pos - start); 667 return; 668 } 669 start += bsize; 670 } 671 throw new Error ("'pos' (" + pos + ") out of bounds."); 672 } 673 674 677 public final void add(int val) { 678 checkImmutable(); 679 680 int size = block_list.size(); 681 IntegerListBlockInterface block = 682 (IntegerListBlockInterface) block_list.get(size - 1); 683 insertIntoBlock(val, size - 1, block, block.size()); 684 } 685 686 690 public final int remove(int pos) { 691 checkImmutable(); 692 693 int size = block_list.size(); 694 int start = 0; 695 for (int i = 0; i < size; ++i) { 696 IntegerListBlockInterface block = 697 (IntegerListBlockInterface) block_list.get(i); 698 int bsize = block.size(); 699 if (pos >= start && pos <= start + bsize) { 700 return removeFromBlock(i, block, pos - start); 701 } 702 start += bsize; 703 } 704 throw new Error ("'pos' (" + pos + ") out of bounds."); 705 } 706 707 709 715 public final boolean contains(int val) { 716 int block_num = findLastBlock(val); 717 718 if (block_num < 0) { 719 return false; 721 } 722 723 IntegerListBlockInterface block = 725 (IntegerListBlockInterface) block_list.get(block_num); 726 727 int sr = block.searchLast(val); 729 return sr >= 0; 730 731 } 732 733 736 public final void insertSort(int val) { 737 checkImmutable(); 738 739 int block_num = findLastBlock(val); 740 741 if (block_num < 0) { 742 block_num = (-(block_num + 1)) - 1; 745 if (block_num < 0) { 746 block_num = 0; 747 } 748 } 749 750 IntegerListBlockInterface block = 752 (IntegerListBlockInterface) block_list.get(block_num); 753 754 int i = block.searchLast(val); 756 if (i < 0) { 757 i = -(i + 1); 758 } 759 else { 760 i = i + 1; 761 } 764 765 insertIntoBlock(val, block_num, block, i); 767 768 } 769 770 776 public final boolean uniqueInsertSort(int val) { 777 checkImmutable(); 778 779 int block_num = findLastBlock(val); 780 781 if (block_num < 0) { 782 block_num = (-(block_num + 1)) - 1; 785 if (block_num < 0) { 786 block_num = 0; 787 } 788 } 789 790 IntegerListBlockInterface block = 792 (IntegerListBlockInterface) block_list.get(block_num); 793 794 int i = block.searchLast(val); 796 if (i < 0) { 797 i = -(i + 1); 798 } 799 else { 800 return false; 802 } 803 804 insertIntoBlock(val, block_num, block, i); 806 807 return true; 809 810 } 811 812 818 public final boolean removeSort(int val) { 819 checkImmutable(); 820 821 int block_num = findLastBlock(val); 822 823 if (block_num < 0) { 824 block_num = (-(block_num + 1)) - 1; 827 if (block_num < 0) { 828 block_num = 0; 829 } 830 } 831 832 IntegerListBlockInterface block = 834 (IntegerListBlockInterface) block_list.get(block_num); 835 836 int i = block.searchLast(val); 838 if (i < 0) { 839 return false; 842 } 843 844 int val_removed = removeFromBlock(block_num, block, i); 846 if (val != val_removed) { 847 throw new Error ("Incorrect value removed."); 848 } 849 850 return true; 852 853 } 854 855 856 857 858 859 860 861 862 863 864 870 public final boolean contains(Object key, IndexComparator c) { 871 int block_num = findBlockContaining(key, c); 872 873 if (block_num < 0) { 874 return false; 876 } 877 878 IntegerListBlockInterface block = 880 (IntegerListBlockInterface) block_list.get(block_num); 881 882 int sr = block.binarySearch(key, c); 884 return sr >= 0; 885 886 } 887 888 894 public final void insertSort(Object key, int val, IndexComparator c) { 895 checkImmutable(); 896 897 int block_num = findLastBlock(key, c); 898 899 if (block_num < 0) { 900 block_num = (-(block_num + 1)) - 1; 903 if (block_num < 0) { 904 block_num = 0; 905 } 906 } 907 908 IntegerListBlockInterface block = 910 (IntegerListBlockInterface) block_list.get(block_num); 911 912 int i = block.searchLast(key, c); 914 if (i < 0) { 915 i = -(i + 1); 916 } 917 else { 918 i = i + 1; 919 } 922 923 insertIntoBlock(val, block_num, block, i); 925 926 } 927 928 935 public final int removeSort(Object key, int val, IndexComparator c) { 936 checkImmutable(); 937 938 final int orig_block_num = findFirstBlock(key, c); 940 int block_num = orig_block_num; 941 int l_block_num = block_list.size() - 1; 942 944 if (block_num < 0) { 945 throw new Error ("Value (" + key + ") was not found in the list."); 947 } 948 949 IntegerListBlockInterface block = 951 (IntegerListBlockInterface) block_list.get(block_num); 952 int i = block.iterativeSearch(val); 954 while (i == -1) { 955 ++block_num; 957 if (block_num > l_block_num) { 958 throw new Error ("Value (" + key + ") was not found in the list."); 959 } 960 block = (IntegerListBlockInterface) block_list.get(block_num); 961 i = block.iterativeSearch(val); 963 } 964 965 973 return removeFromBlock(block_num, block, i); 975 976 } 977 978 979 980 981 982 983 984 985 986 987 988 989 993 public final int searchLast(Object key, IndexComparator c) { 994 int block_num = findLastBlock(key, c); 995 int sr; 996 997 if (block_num < 0) { 998 block_num = (-(block_num + 1)); sr = -1; 1001 } 1002 1003 else { 1004 IntegerListBlockInterface block = 1006 (IntegerListBlockInterface) block_list.get(block_num); 1007 1008 sr = block.searchLast(key, c); 1010 } 1011 1012 int offset = 0; 1013 for (int i = 0; i < block_num; ++i) { 1014 IntegerListBlockInterface block = 1015 (IntegerListBlockInterface) block_list.get(i); 1016 offset += block.size(); 1017 } 1018 1019 if (sr >= 0) { 1020 return offset + sr; 1021 } 1022 else { 1023 return -offset + sr; 1024 } 1025 1026 } 1027 1028 1032 public final int searchFirst(Object key, IndexComparator c) { 1033 int block_num = findFirstBlock(key, c); 1034 int sr; 1035 1036 if (block_num < 0) { 1037 block_num = (-(block_num + 1)); sr = -1; 1041 } 1042 1043 else { 1044 IntegerListBlockInterface block = 1046 (IntegerListBlockInterface) block_list.get(block_num); 1047 1048 sr = block.searchFirst(key, c); 1050 } 1051 1052 int offset = 0; 1053 for (int i = 0; i < block_num; ++i) { 1054 IntegerListBlockInterface block = 1055 (IntegerListBlockInterface) block_list.get(i); 1056 offset += block.size(); 1057 } 1058 1059 if (sr >= 0) { 1060 return offset + sr; 1061 } 1062 else { 1063 return -offset + sr; 1064 } 1065 1066 } 1067 1068 1070 1071 1074 private final class BILIterator implements IntegerIterator { 1075 1076 1077 private int start_offset; 1078 private int end_offset; 1079 private IntegerListBlockInterface current_block; 1080 private int current_block_size; 1081 private int block_index; 1082 private int block_offset; 1083 private int cur_offset; 1084 1085 public BILIterator(int start_offset, int end_offset) { 1086 this.start_offset = start_offset; 1087 this.end_offset = end_offset; 1088 cur_offset = start_offset - 1; 1089 1090 if (end_offset >= start_offset) { 1091 setupVars(start_offset - 1); 1093 } 1094 1095 } 1096 1097 1100 private void setupVars(int pos) { 1101 int size = block_list.size(); 1102 int start = 0; 1103 for (block_index = 0; block_index < size; ++block_index) { 1104 IntegerListBlockInterface block = 1105 (IntegerListBlockInterface) block_list.get(block_index); 1106 int bsize = block.size(); 1107 if (pos < start + bsize) { 1108 block_offset = pos - start; 1109 if (block_offset < 0) { 1110 block_offset = -1; 1111 } 1112 current_block = block; 1113 current_block_size = bsize; 1114 return; 1115 } 1116 start += bsize; 1117 } 1118 throw new Error ("'pos' (" + pos + ") out of bounds."); 1119 } 1120 1121 1122 1124 public boolean hasNext() { 1125 return cur_offset < end_offset; 1126 } 1127 1128 public int next() { 1129 ++block_offset; 1130 ++cur_offset; 1131 if (block_offset >= current_block_size) { 1132 ++block_index; 1133 current_block = 1134 (IntegerListBlockInterface) block_list.get(block_index); 1135 current_block_size = current_block.size(); 1137 block_offset = 0; 1138 } 1139 return current_block.intAt(block_offset); 1140 } 1141 1142 public boolean hasPrevious() { 1143 return cur_offset > start_offset; 1144 } 1145 1146 private void walkBack() { 1147 --block_offset; 1148 --cur_offset; 1149 if (block_offset < 0) { 1150 if (block_index > 0) { 1151 --block_index; 1153 current_block = 1154 (IntegerListBlockInterface) block_list.get(block_index); 1155 current_block_size = current_block.size(); 1157 block_offset = current_block.size() - 1; 1158 } 1159 } 1160 } 1161 1162 public int previous() { 1163 walkBack(); 1164 return current_block.intAt(block_offset); 1165 } 1166 1167 public void remove() { 1168 checkImmutable(); 1169 1170 int orig_block_count = block_list.size(); 1174 removeFromBlock(block_index, current_block, block_offset); 1175 1176 if (orig_block_count == block_list.size()) { 1178 --current_block_size; 1180 walkBack(); 1181 } 1182 else { 1183 --cur_offset; 1184 setupVars(cur_offset); 1185 } 1186 --end_offset; 1187 } 1188 1189 } 1190 1191 1192 1198 public IntegerIterator iterator(int start_offset, int end_offset) { 1199 return new BILIterator(start_offset, end_offset); 1200 } 1201 1202 1208 public IntegerIterator iterator() { 1209 return iterator(0, size() - 1); 1210 } 1211 1212 1213 1214 1215 1216 1217 1218 1220 public String toString() { 1221 StringBuffer buf = new StringBuffer (); 1222 buf.append("Blocks: " + block_list.size() + "\n"); 1223 for (int i = 0; i < block_list.size(); ++i) { 1224 buf.append("Block (" + i + "): " + block_list.get(i).toString() + "\n"); 1225 } 1226 return new String (buf); 1227 } 1228 1229 public void checkSorted(IndexComparator c) { 1230 IntegerIterator iterator = iterator(0, size() - 1); 1231 checkSorted(iterator, c); 1232 } 1233 1234 public static void checkSorted(IntegerIterator iterator, IndexComparator c) { 1235 if (iterator.hasNext()) { 1236 int last_index = iterator.next(); 1237 while (iterator.hasNext()) { 1238 int cur = iterator.next(); 1239 if (c.compare(cur, last_index) < 0) { 1240 throw new Error ("List not sorted!"); 1241 } 1242 last_index = cur; 1243 } 1244 } 1245 } 1246 1247 1248} 1249 | Popular Tags |