Compare commits
6 Commits
948973fee7
...
bb359c9fe7
| Author | SHA1 | Date | |
|---|---|---|---|
| bb359c9fe7 | |||
|
|
e41e5e4a0c | ||
|
|
6bdc38ef77 | ||
|
|
53824b1147 | ||
|
|
1ade7ffdde | ||
|
|
47cbeb649f |
@@ -559,52 +559,63 @@
|
|||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
no_rect.fill('yellow');
|
no_rect.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
left_subtree_null.fill('white');
|
left_subtree_null.fill('white');
|
||||||
no_rect.fill('white');
|
no_rect.fill('white');
|
||||||
find_inorder_predecessor.fill('yellow');
|
find_inorder_predecessor.fill('yellow');
|
||||||
stage.find('#node_2')[0].fill('lime');
|
stage.find('#node_2')[0].fill('lime');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
stage.find('#node_2')[0].fill('white');
|
stage.find('#node_2')[0].fill('white');
|
||||||
stage.find('#node_5')[0].fill('lime');
|
stage.find('#node_5')[0].fill('lime');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6:
|
case 6:
|
||||||
stage.find('#node_5')[0].fill('white');
|
stage.find('#node_5')[0].fill('white');
|
||||||
stage.find('#node_7')[0].fill('lime');
|
stage.find('#node_7')[0].fill('lime');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 7:
|
case 7:
|
||||||
find_inorder_predecessor.fill('white');
|
find_inorder_predecessor.fill('white');
|
||||||
where_right.fill('yellow');
|
where_right.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
null_rect.fill('yellow');
|
null_rect.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
where_right.fill('white');
|
where_right.fill('white');
|
||||||
null_rect.fill('white');
|
null_rect.fill('white');
|
||||||
set_current.fill('yellow');
|
set_current.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 10:
|
case 10:
|
||||||
node7to1.show();
|
node7to1.show();
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 11:
|
case 11:
|
||||||
stage.find('#node_1')[0].fill('white');
|
stage.find('#node_1')[0].fill('white');
|
||||||
stage.find('#node_2')[0].fill('yellow');
|
stage.find('#node_2')[0].fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 12:
|
case 12:
|
||||||
set_current.fill('white');
|
set_current.fill('white');
|
||||||
left_subtree_null.fill('yellow');
|
left_subtree_null.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 13:
|
case 13:
|
||||||
no_rect.fill('yellow');
|
no_rect.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 14:
|
case 14:
|
||||||
@@ -613,355 +624,442 @@
|
|||||||
find_inorder_predecessor.fill('yellow');
|
find_inorder_predecessor.fill('yellow');
|
||||||
stage.find('#node_7')[0].fill('white');
|
stage.find('#node_7')[0].fill('white');
|
||||||
stage.find('#node_4')[0].fill('lime');
|
stage.find('#node_4')[0].fill('lime');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 15:
|
case 15:
|
||||||
find_inorder_predecessor.fill('white');
|
find_inorder_predecessor.fill('white');
|
||||||
where_right.fill('yellow');
|
where_right.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 16:
|
case 16:
|
||||||
null_rect.fill('yellow');
|
null_rect.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 17:
|
case 17:
|
||||||
where_right.fill('white');
|
where_right.fill('white');
|
||||||
null_rect.fill('white');
|
null_rect.fill('white');
|
||||||
set_current.fill('yellow');
|
set_current.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 18:
|
case 18:
|
||||||
node4to2.show();
|
node4to2.show();
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 19:
|
case 19:
|
||||||
stage.find('#node_2')[0].fill('white');
|
stage.find('#node_2')[0].fill('white');
|
||||||
stage.find('#node_4')[0].fill('yellow');
|
stage.find('#node_4')[0].fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 20:
|
case 20:
|
||||||
set_current.fill('white');
|
set_current.fill('white');
|
||||||
left_subtree_null.fill('yellow');
|
left_subtree_null.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 21:
|
case 21:
|
||||||
yes_rect.fill('yellow');
|
yes_rect.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 22:
|
case 22:
|
||||||
left_subtree_null.fill('white');
|
left_subtree_null.fill('white');
|
||||||
yes_rect.fill('white');
|
yes_rect.fill('white');
|
||||||
print_move_right.fill('yellow');
|
print_move_right.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 23:
|
case 23:
|
||||||
console_text.text('Console:\n4');
|
console_text.text('Console:\n4');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 24:
|
case 24:
|
||||||
stage.find('#node_4')[0].fill('white');
|
stage.find('#node_4')[0].fill('white');
|
||||||
stage.find('#node_2')[0].fill('yellow');
|
stage.find('#node_2')[0].fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 25:
|
case 25:
|
||||||
print_move_right.fill('white');
|
print_move_right.fill('white');
|
||||||
left_subtree_null.fill('yellow');
|
left_subtree_null.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 26:
|
case 26:
|
||||||
no_rect.fill('yellow');
|
no_rect.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 27:
|
case 27:
|
||||||
left_subtree_null.fill('white');
|
left_subtree_null.fill('white');
|
||||||
no_rect.fill('white');
|
no_rect.fill('white');
|
||||||
find_inorder_predecessor.fill('yellow');
|
find_inorder_predecessor.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 28:
|
case 28:
|
||||||
stage.find('#node_4')[0].fill('lime');
|
stage.find('#node_4')[0].fill('lime');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 29:
|
case 29:
|
||||||
find_inorder_predecessor.fill('white');
|
find_inorder_predecessor.fill('white');
|
||||||
where_right.fill('yellow');
|
where_right.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 30:
|
case 30:
|
||||||
current_rect.fill('yellow');
|
current_rect.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 31:
|
case 31:
|
||||||
where_right.fill('white');
|
where_right.fill('white');
|
||||||
current_rect.fill('white');
|
current_rect.fill('white');
|
||||||
set_null.fill('yellow');
|
set_null.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 32:
|
case 32:
|
||||||
node4to2.hide();
|
node4to2.hide();
|
||||||
console_text.text('Console:\n4 2');
|
console_text.text('Console:\n4 2');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 33:
|
case 33:
|
||||||
stage.find('#node_4')[0].fill('white');
|
stage.find('#node_4')[0].fill('white');
|
||||||
stage.find('#node_2')[0].fill('white');
|
stage.find('#node_2')[0].fill('white');
|
||||||
stage.find('#node_5')[0].fill('yellow');
|
stage.find('#node_5')[0].fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 34:
|
case 34:
|
||||||
set_null.fill('white');
|
set_null.fill('white');
|
||||||
left_subtree_null.fill('yellow');
|
left_subtree_null.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 35:
|
case 35:
|
||||||
no_rect.fill('yellow');
|
no_rect.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 36:
|
case 36:
|
||||||
left_subtree_null.fill('white');
|
left_subtree_null.fill('white');
|
||||||
no_rect.fill('white');
|
no_rect.fill('white');
|
||||||
find_inorder_predecessor.fill('yellow');
|
find_inorder_predecessor.fill('yellow');
|
||||||
stage.find('#node_6')[0].fill('lime');
|
stage.find('#node_6')[0].fill('lime');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 37:
|
case 37:
|
||||||
find_inorder_predecessor.fill('white');
|
find_inorder_predecessor.fill('white');
|
||||||
where_right.fill('yellow');
|
where_right.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 38:
|
case 38:
|
||||||
null_rect.fill('yellow');
|
null_rect.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 39:
|
case 39:
|
||||||
where_right.fill('white');
|
where_right.fill('white');
|
||||||
null_rect.fill('white');
|
null_rect.fill('white');
|
||||||
set_current.fill('yellow');
|
set_current.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 40:
|
case 40:
|
||||||
node6to5.show();
|
node6to5.show();
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 41:
|
case 41:
|
||||||
stage.find('#node_5')[0].fill('white');
|
stage.find('#node_5')[0].fill('white');
|
||||||
stage.find('#node_6')[0].fill('yellow');
|
stage.find('#node_6')[0].fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 42:
|
case 42:
|
||||||
set_current.fill('white');
|
set_current.fill('white');
|
||||||
left_subtree_null.fill('yellow');
|
left_subtree_null.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 43:
|
case 43:
|
||||||
yes_rect.fill('yellow');
|
yes_rect.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 44:
|
case 44:
|
||||||
left_subtree_null.fill('white');
|
left_subtree_null.fill('white');
|
||||||
yes_rect.fill('white');
|
yes_rect.fill('white');
|
||||||
print_move_right.fill('yellow');
|
print_move_right.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 45:
|
case 45:
|
||||||
console_text.text('Console:\n4 2 6');
|
console_text.text('Console:\n4 2 6');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 46:
|
case 46:
|
||||||
stage.find('#node_6')[0].fill('white');
|
stage.find('#node_6')[0].fill('white');
|
||||||
stage.find('#node_5')[0].fill('yellow');
|
stage.find('#node_5')[0].fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 47:
|
case 47:
|
||||||
print_move_right.fill('white');
|
print_move_right.fill('white');
|
||||||
left_subtree_null.fill('yellow');
|
left_subtree_null.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 48:
|
case 48:
|
||||||
no_rect.fill('yellow');
|
no_rect.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 49:
|
case 49:
|
||||||
left_subtree_null.fill('white');
|
left_subtree_null.fill('white');
|
||||||
no_rect.fill('white');
|
no_rect.fill('white');
|
||||||
find_inorder_predecessor.fill('yellow');
|
find_inorder_predecessor.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 50:
|
case 50:
|
||||||
stage.find('#node_6')[0].fill('lime');
|
stage.find('#node_6')[0].fill('lime');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 51:
|
case 51:
|
||||||
find_inorder_predecessor.fill('white');
|
find_inorder_predecessor.fill('white');
|
||||||
where_right.fill('yellow');
|
where_right.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 52:
|
case 52:
|
||||||
current_rect.fill('yellow');
|
current_rect.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 53:
|
case 53:
|
||||||
where_right.fill('white');
|
where_right.fill('white');
|
||||||
current_rect.fill('white');
|
current_rect.fill('white');
|
||||||
set_null.fill('yellow');
|
set_null.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 54:
|
case 54:
|
||||||
node6to5.hide();
|
node6to5.hide();
|
||||||
console_text.text('Console:\n4 2 6 5');
|
console_text.text('Console:\n4 2 6 5');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 55:
|
case 55:
|
||||||
stage.find('#node_6')[0].fill('white');
|
stage.find('#node_6')[0].fill('white');
|
||||||
stage.find('#node_5')[0].fill('white');
|
stage.find('#node_5')[0].fill('white');
|
||||||
stage.find('#node_7')[0].fill('yellow');
|
stage.find('#node_7')[0].fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 56:
|
case 56:
|
||||||
set_null.fill('white');
|
set_null.fill('white');
|
||||||
left_subtree_null.fill('yellow');
|
left_subtree_null.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 57:
|
case 57:
|
||||||
yes_rect.fill('yellow');
|
yes_rect.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 58:
|
case 58:
|
||||||
left_subtree_null.fill('white');
|
left_subtree_null.fill('white');
|
||||||
yes_rect.fill('white');
|
yes_rect.fill('white');
|
||||||
print_move_right.fill('yellow');
|
print_move_right.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 59:
|
case 59:
|
||||||
console_text.text('Console:\n4 2 6 5 7');
|
console_text.text('Console:\n4 2 6 5 7');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 60:
|
case 60:
|
||||||
stage.find('#node_7')[0].fill('white');
|
stage.find('#node_7')[0].fill('white');
|
||||||
stage.find('#node_1')[0].fill('yellow');
|
stage.find('#node_1')[0].fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 61:
|
case 61:
|
||||||
print_move_right.fill('white');
|
print_move_right.fill('white');
|
||||||
left_subtree_null.fill('yellow');
|
left_subtree_null.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 62:
|
case 62:
|
||||||
no_rect.fill('yellow');
|
no_rect.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 63:
|
case 63:
|
||||||
left_subtree_null.fill('white');
|
left_subtree_null.fill('white');
|
||||||
no_rect.fill('white');
|
no_rect.fill('white');
|
||||||
find_inorder_predecessor.fill('yellow');
|
find_inorder_predecessor.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 64:
|
case 64:
|
||||||
stage.find('#node_2')[0].fill('lime');
|
stage.find('#node_2')[0].fill('lime');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 65:
|
case 65:
|
||||||
stage.find('#node_2')[0].fill('white');
|
stage.find('#node_2')[0].fill('white');
|
||||||
stage.find('#node_5')[0].fill('lime');
|
stage.find('#node_5')[0].fill('lime');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 66:
|
case 66:
|
||||||
stage.find('#node_5')[0].fill('white');
|
stage.find('#node_5')[0].fill('white');
|
||||||
stage.find('#node_7')[0].fill('lime');
|
stage.find('#node_7')[0].fill('lime');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 67:
|
case 67:
|
||||||
find_inorder_predecessor.fill('white');
|
find_inorder_predecessor.fill('white');
|
||||||
where_right.fill('yellow');
|
where_right.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 68:
|
case 68:
|
||||||
current_rect.fill('yellow');
|
current_rect.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
case 69:
|
case 69:
|
||||||
where_right.fill('white');
|
where_right.fill('white');
|
||||||
current_rect.fill('white');
|
current_rect.fill('white');
|
||||||
set_null.fill('yellow');
|
set_null.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 70:
|
case 70:
|
||||||
console_text.text('Console:\n4 2 6 5 7 1');
|
console_text.text('Console:\n4 2 6 5 7 1');
|
||||||
node7to1.hide();
|
node7to1.hide();
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 71:
|
case 71:
|
||||||
stage.find('#node_7')[0].fill('white');
|
stage.find('#node_7')[0].fill('white');
|
||||||
stage.find('#node_1')[0].fill('white');
|
stage.find('#node_1')[0].fill('white');
|
||||||
stage.find('#node_3')[0].fill('yellow');
|
stage.find('#node_3')[0].fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 72:
|
case 72:
|
||||||
set_null.fill('white');
|
set_null.fill('white');
|
||||||
left_subtree_null.fill('yellow');
|
left_subtree_null.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 73:
|
case 73:
|
||||||
yes_rect.fill('yellow');
|
yes_rect.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 74:
|
case 74:
|
||||||
left_subtree_null.fill('white');
|
left_subtree_null.fill('white');
|
||||||
yes_rect.fill('white');
|
yes_rect.fill('white');
|
||||||
print_move_right.fill('yellow');
|
print_move_right.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 75:
|
case 75:
|
||||||
console_text.text('Console:\n4 2 6 5 7 1 3');
|
console_text.text('Console:\n4 2 6 5 7 1 3');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 76:
|
case 76:
|
||||||
stage.find('#node_3')[0].fill('white');
|
stage.find('#node_3')[0].fill('white');
|
||||||
stage.find('#node_8')[0].fill('yellow');
|
stage.find('#node_8')[0].fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 77:
|
case 77:
|
||||||
print_move_right.fill('white');
|
print_move_right.fill('white');
|
||||||
left_subtree_null.fill('yellow');
|
left_subtree_null.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 78:
|
case 78:
|
||||||
no_rect.fill('yellow');
|
no_rect.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 79:
|
case 79:
|
||||||
left_subtree_null.fill('white');
|
left_subtree_null.fill('white');
|
||||||
no_rect.fill('white');
|
no_rect.fill('white');
|
||||||
find_inorder_predecessor.fill('yellow');
|
find_inorder_predecessor.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 80:
|
case 80:
|
||||||
stage.find('#node_9')[0].fill('lime');
|
stage.find('#node_9')[0].fill('lime');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 81:
|
case 81:
|
||||||
find_inorder_predecessor.fill('white');
|
find_inorder_predecessor.fill('white');
|
||||||
where_right.fill('yellow');
|
where_right.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 82:
|
case 82:
|
||||||
null_rect.fill('yellow');
|
null_rect.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 83:
|
case 83:
|
||||||
where_right.fill('white');
|
where_right.fill('white');
|
||||||
null_rect.fill('white');
|
null_rect.fill('white');
|
||||||
set_current.fill('yellow');
|
set_current.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 84:
|
case 84:
|
||||||
node9to8.show();
|
node9to8.show();
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 85:
|
case 85:
|
||||||
stage.find('#node_8')[0].fill('white');
|
stage.find('#node_8')[0].fill('white');
|
||||||
stage.find('#node_9')[0].fill('yellow');
|
stage.find('#node_9')[0].fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 86:
|
case 86:
|
||||||
set_current.fill('white');
|
set_current.fill('white');
|
||||||
left_subtree_null.fill('yellow');
|
left_subtree_null.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 87:
|
case 87:
|
||||||
yes_rect.fill('yellow');
|
yes_rect.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 88:
|
case 88:
|
||||||
left_subtree_null.fill('white');
|
left_subtree_null.fill('white');
|
||||||
yes_rect.fill('white');
|
yes_rect.fill('white');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 89:
|
case 89:
|
||||||
print_move_right.fill('yellow');
|
print_move_right.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 90:
|
case 90:
|
||||||
console_text.text('Console:\n4 2 6 5 7 1 3 9');
|
console_text.text('Console:\n4 2 6 5 7 1 3 9');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 91:
|
case 91:
|
||||||
stage.find('#node_8')[0].fill('yellow');
|
stage.find('#node_8')[0].fill('yellow');
|
||||||
stage.find('#node_9')[0].fill('white');
|
stage.find('#node_9')[0].fill('white');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 92:
|
case 92:
|
||||||
print_move_right.fill('white');
|
print_move_right.fill('white');
|
||||||
left_subtree_null.fill('yellow');
|
left_subtree_null.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 93:
|
case 93:
|
||||||
no_rect.fill('yellow');
|
no_rect.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 94:
|
case 94:
|
||||||
left_subtree_null.fill('white');
|
left_subtree_null.fill('white');
|
||||||
no_rect.fill('white');
|
no_rect.fill('white');
|
||||||
find_inorder_predecessor.fill('yellow');
|
find_inorder_predecessor.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 95:
|
case 95:
|
||||||
stage.find('#node_9')[0].fill('lime');
|
stage.find('#node_9')[0].fill('lime');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 96:
|
case 96:
|
||||||
find_inorder_predecessor.fill('white');
|
find_inorder_predecessor.fill('white');
|
||||||
where_right.fill('yellow');
|
where_right.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 97:
|
case 97:
|
||||||
current_rect.fill('yellow');
|
current_rect.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 98:
|
case 98:
|
||||||
where_right.fill('white');
|
where_right.fill('white');
|
||||||
current_rect.fill('white');
|
current_rect.fill('white');
|
||||||
set_null.fill('yellow');
|
set_null.fill('yellow');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 99:
|
case 99:
|
||||||
console_text.text('Console:\n4 2 6 5 7 1 3 9 8');
|
console_text.text('Console:\n4 2 6 5 7 1 3 9 8');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 100:
|
case 100:
|
||||||
node9to8.hide();
|
node9to8.hide();
|
||||||
stage.find('#node_8')[0].fill('white');
|
stage.find('#node_8')[0].fill('white');
|
||||||
stage.find('#node_9')[0].fill('white');
|
stage.find('#node_9')[0].fill('white');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
case 101:
|
case 101:
|
||||||
start_from_root.fill('red');
|
start_from_root.fill('red');
|
||||||
@@ -971,6 +1069,7 @@
|
|||||||
where_right.fill('red');
|
where_right.fill('red');
|
||||||
set_current.fill('red');
|
set_current.fill('red');
|
||||||
set_null.fill('red');
|
set_null.fill('red');
|
||||||
|
layer.draw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
@@ -979,7 +1078,6 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//while (step < )
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,23 +1,143 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
bool isGood(int n) {
|
// Compute the sum of the squares of a number's digits.
|
||||||
|
int sumOfSquaresOfDigits(int x) {
|
||||||
|
int sum = 0;
|
||||||
|
while (x > 0) {
|
||||||
|
int digit = x % 10;
|
||||||
|
sum += digit * digit;
|
||||||
|
x /= 10;
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
// std::unordered_set
|
||||||
|
bool isGood_unordered_set(int n) {
|
||||||
|
std::unordered_set<int> visited;
|
||||||
|
while (n != 1 && visited.find(n) == visited.end()) {
|
||||||
|
visited.insert(n);
|
||||||
|
n = sumOfSquaresOfDigits(n);
|
||||||
|
}
|
||||||
|
return (n == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// std::unordered_map
|
||||||
|
bool isGood_unordered_map(int n) {
|
||||||
|
// We only need to mark that we have "seen" a number.
|
||||||
|
// The bool value is arbitrary; storing true is enough.
|
||||||
|
std::unordered_map<int, bool> visited;
|
||||||
|
while (n != 1 && visited.find(n) == visited.end()) {
|
||||||
|
visited[n] = true; // Mark n as visited
|
||||||
|
n = sumOfSquaresOfDigits(n);
|
||||||
|
}
|
||||||
|
return (n == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyHashSet {
|
||||||
|
private:
|
||||||
|
// store integers in a vector of lists
|
||||||
|
std::vector< std::list<int> > table;
|
||||||
|
int num_elements;
|
||||||
|
static const int DEFAULT_SIZE = 16;
|
||||||
|
static const double LOAD_FACTOR_THRESHOLD;
|
||||||
|
|
||||||
|
// A simple hash function for int
|
||||||
|
int hashFunction(int key) const {
|
||||||
|
// take abs value
|
||||||
|
int h = key < 0 ? -key : key;
|
||||||
|
return h % (int)table.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void rehash() {
|
||||||
|
int newSize = (int)table.size() * 2; // doubling
|
||||||
|
std::vector< std::list<int> > newTable(newSize);
|
||||||
|
|
||||||
|
// re-insert all existing elements into newTable
|
||||||
|
for (auto &chain : table) {
|
||||||
|
for (int val : chain) {
|
||||||
|
int h = (val < 0 ? -val : val) % newSize;
|
||||||
|
newTable[h].push_back(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
table.swap(newTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rehashIfNeeded() {
|
||||||
|
// If load factor = num_elements / table.size() is too big, rehash
|
||||||
|
double load_factor = (double)num_elements / (double)table.size();
|
||||||
|
if (load_factor > LOAD_FACTOR_THRESHOLD) {
|
||||||
|
rehash();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Constructor
|
||||||
|
MyHashSet(int initialSize = DEFAULT_SIZE)
|
||||||
|
: table(initialSize), num_elements(0) {}
|
||||||
|
|
||||||
|
// Return true if key is found
|
||||||
|
bool find(int key) const {
|
||||||
|
int h = hashFunction(key);
|
||||||
|
// Search the list in bin h
|
||||||
|
for (int val : table[h]) {
|
||||||
|
if (val == key) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert key if not already in the hash set
|
||||||
|
void insert(int key) {
|
||||||
|
if (!find(key)) {
|
||||||
|
int h = hashFunction(key);
|
||||||
|
table[h].push_back(key);
|
||||||
|
num_elements++;
|
||||||
|
rehashIfNeeded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const double MyHashSet::LOAD_FACTOR_THRESHOLD = 1.0;
|
||||||
|
|
||||||
|
// The "isGood" function that uses MyHashSet
|
||||||
|
bool isGood_custom_hash(int n) {
|
||||||
|
MyHashSet visited;
|
||||||
|
while (n != 1 && !visited.find(n)) {
|
||||||
|
visited.insert(n);
|
||||||
|
n = sumOfSquaresOfDigits(n);
|
||||||
|
}
|
||||||
|
return (n == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
// Test cases
|
|
||||||
// 2, 4, 5, 6, 17, 18, 20 are not good numbers.
|
|
||||||
// 1, 7, 10, 13, 19, 23, 28, 68 are good numbers.
|
|
||||||
|
|
||||||
int testCases[] = {2,4,5,6,17,18,20,1,7,10,13,19,23,28,68};
|
int testCases[] = {2,4,5,6,17,18,20,1,7,10,13,19,23,28,68};
|
||||||
|
|
||||||
|
std::cout << "=== Using std::unordered_set ===" << std::endl;
|
||||||
for (int n : testCases) {
|
for (int n : testCases) {
|
||||||
if (isGood(n)) {
|
if (isGood_unordered_set(n))
|
||||||
std::cout << n << " is a good number." << std::endl;
|
std::cout << n << " is a good number." << std::endl;
|
||||||
} else {
|
else
|
||||||
|
std::cout << n << " is not a good number." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "\n=== Using std::unordered_map ===" << std::endl;
|
||||||
|
for (int n : testCases) {
|
||||||
|
if (isGood_unordered_map(n))
|
||||||
|
std::cout << n << " is a good number." << std::endl;
|
||||||
|
else
|
||||||
|
std::cout << n << " is not a good number." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "\n=== Using custom separate-chaining HashSet ===" << std::endl;
|
||||||
|
for (int n : testCases) {
|
||||||
|
if (isGood_custom_hash(n))
|
||||||
|
std::cout << n << " is a good number." << std::endl;
|
||||||
|
else
|
||||||
std::cout << n << " is not a good number." << std::endl;
|
std::cout << n << " is not a good number." << std::endl;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,113 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
// A minimal separate-chaining HashSet for integers.
|
||||||
|
class MyHashSet {
|
||||||
|
private:
|
||||||
|
std::vector< std::list<int> > table;
|
||||||
|
int num_elements;
|
||||||
|
static const int DEFAULT_SIZE = 16;
|
||||||
|
static const double LOAD_FACTOR_THRESHOLD;
|
||||||
|
|
||||||
|
int hashFunction(int key) const {
|
||||||
|
int h = key < 0 ? -key : key; // handle negative
|
||||||
|
return h % (int)table.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void rehash() {
|
||||||
|
int newSize = (int)table.size() * 2;
|
||||||
|
std::vector< std::list<int> > newTable(newSize);
|
||||||
|
|
||||||
|
for (auto &chain : table) {
|
||||||
|
for (int val : chain) {
|
||||||
|
int h = (val < 0 ? -val : val) % newSize;
|
||||||
|
newTable[h].push_back(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
table.swap(newTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rehashIfNeeded() {
|
||||||
|
double load_factor = (double)num_elements / (double)table.size();
|
||||||
|
if (load_factor > LOAD_FACTOR_THRESHOLD) {
|
||||||
|
rehash();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
MyHashSet(int initialSize = DEFAULT_SIZE)
|
||||||
|
: table(initialSize), num_elements(0) {}
|
||||||
|
|
||||||
|
bool find(int key) const {
|
||||||
|
int h = hashFunction(key);
|
||||||
|
for (int val : table[h]) {
|
||||||
|
if (val == key) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void insert(int key) {
|
||||||
|
if (!find(key)) {
|
||||||
|
int h = hashFunction(key);
|
||||||
|
table[h].push_back(key);
|
||||||
|
num_elements++;
|
||||||
|
rehashIfNeeded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const double MyHashSet::LOAD_FACTOR_THRESHOLD = 1.0;
|
||||||
|
|
||||||
int longestConsecutive(std::vector<int>& nums) {
|
int longestConsecutive(std::vector<int>& nums) {
|
||||||
|
if (nums.empty()) return 0;
|
||||||
|
|
||||||
|
// Insert all numbers into the custom hash set
|
||||||
|
MyHashSet set;
|
||||||
|
for (int n : nums) {
|
||||||
|
set.insert(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
int longestStreak = 0;
|
||||||
|
// For each number, only count a sequence if it's a "start"
|
||||||
|
// i.e., if (n-1) is NOT in the set
|
||||||
|
for (int n : nums) {
|
||||||
|
if (!set.find(n - 1)) {
|
||||||
|
// n is the start of a consecutive sequence
|
||||||
|
int currentNum = n;
|
||||||
|
int currentStreak = 1;
|
||||||
|
|
||||||
|
while (set.find(currentNum + 1)) {
|
||||||
|
currentNum++;
|
||||||
|
currentStreak++;
|
||||||
|
}
|
||||||
|
if (currentStreak > longestStreak) {
|
||||||
|
longestStreak = currentStreak;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return longestStreak;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
//std::vector<int> nums = {100, 4, 200, 1, 3, 2};
|
// You can change these test vectors to experiment:
|
||||||
std::vector<int> nums = {100, 4, 200, 1, 3, 2, 2, 2, 2, 3};
|
//std::vector<int> nums = {100, 4, 200, 1, 3, 2};
|
||||||
//std::vector<int> nums = {100, 4, 200, 1, 3, 2, 5, 6};
|
//std::vector<int> nums = {0,3,7,2,5,8,4,6,0,1};
|
||||||
//std::vector<int> nums = {0,3,7,2,5,8,4,6,0,1};
|
std::vector<int> nums = {100, 4, 200, 1, 3, 2, 2, 2, 2, 3};
|
||||||
//std::vector<int> nums = {100, 4, 200, 201, 202, 203, 205, 204, 1, 3, 2};
|
|
||||||
//std::vector<int> nums = {-3,0,1,2,3,-2,-1,-5};
|
int size = nums.size();
|
||||||
int size = nums.size();
|
std::cout << "for vector {";
|
||||||
std::cout<< "for vector {";
|
for(int i = 0; i < size; i++){
|
||||||
for(int i=0;i<size-1;i++){
|
if(i < size - 1) std::cout << nums[i] << ",";
|
||||||
std::cout<< nums[i] << ",";
|
else std::cout << nums[i];
|
||||||
}
|
}
|
||||||
std::cout<< nums[size-1] << "}" <<std::endl;
|
std::cout << "}\n";
|
||||||
int length = longestConsecutive(nums);
|
|
||||||
std::cout << "The length of the longest consecutive sequence is: " << length << std::endl;
|
int length = longestConsecutive(nums);
|
||||||
return 0;
|
std::cout << "The length of the longest consecutive sequence is: "
|
||||||
|
<< length << std::endl;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
25
labs/priority_queues/README.md
Normal file
25
labs/priority_queues/README.md
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# Lab 10 — Priority Queues
|
||||||
|
|
||||||
|
In this lab, you will use binary heaps to implement the priority queue container. Start by downloading the files:
|
||||||
|
|
||||||
|
[priority_queue.h](priority_queue.h) [test_pq.cpp](test_pq.cpp)
|
||||||
|
|
||||||
|
The code provided in these files is straightforward. test_pq.cpp is a driver and test program, while priority_queue.h is a skeleton implementation. Please take a careful look. You will complete the implementation and add to the main program in lab. In your implementation, be careful when subtracting 1 from an unsigned int whose value is 0; it is not -1!
|
||||||
|
|
||||||
|
## Checkpoint 1:
|
||||||
|
|
||||||
|
Implement and test the push (a.k.a. insert) and the check_heap functions. Recall that push depends on the percolate_up functionality. check_heap, which works either with the heap member variable or with a vector provided from the outside, determines if the vector is properly a heap, meaning that each value is less than or equal to the values of both of its children (if they exist).
|
||||||
|
|
||||||
|
**To complete this checkpoint**: Show a TA or mentor your debugged implementation and discuss the running time of both insert and check_heap.
|
||||||
|
|
||||||
|
## Checkpoint 2:
|
||||||
|
|
||||||
|
Implement and test the pop (a.k.a. delete_min) function and the constructor that builds a valid heap from a vector of values that is in no particular order. Both of these depend on proper implementation of the percolate_down function.
|
||||||
|
|
||||||
|
**To complete this checkpoint**: Show a TA or mentor these additions and the test output.
|
||||||
|
|
||||||
|
## Checkpoint 3:
|
||||||
|
|
||||||
|
Finally, write and test the non-member function that sorts a vector by doing a heap sort. This code should sort the data “in place” and not require a large scratch space (e.g., another vector or list or another priority queue) to store a copy of the data as it is being sorted.
|
||||||
|
|
||||||
|
**To complete this checkpoint**: Show a TA or mentor your completed and debugged heap sort code.
|
||||||
68
labs/priority_queues/priority_queue.h
Normal file
68
labs/priority_queues/priority_queue.h
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
#ifndef priority_queue_h_
|
||||||
|
#define priority_queue_h_
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class priority_queue {
|
||||||
|
private:
|
||||||
|
std::vector<T> m_heap;
|
||||||
|
|
||||||
|
public:
|
||||||
|
priority_queue() {}
|
||||||
|
|
||||||
|
priority_queue( std::vector<T> const& values )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& top() const
|
||||||
|
{
|
||||||
|
assert( !m_heap.empty() );
|
||||||
|
return m_heap[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
void push( const T& entry )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop()
|
||||||
|
{
|
||||||
|
assert( !m_heap.empty() );
|
||||||
|
}
|
||||||
|
|
||||||
|
int size() { return m_heap.size(); }
|
||||||
|
bool empty() { return m_heap.empty(); }
|
||||||
|
|
||||||
|
|
||||||
|
// The following three functions are used for debugging.
|
||||||
|
|
||||||
|
// Check to see that internally the heap property is realized.
|
||||||
|
bool check_heap( )
|
||||||
|
{
|
||||||
|
return this->check_heap( this->m_heap );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check an external vector to see that the heap property is realized.
|
||||||
|
bool check_heap( const std::vector<T>& heap )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// A utility to print the contents of the heap. Use it for debugging.
|
||||||
|
void print_heap( std::ostream & ostr )
|
||||||
|
{
|
||||||
|
for ( unsigned int i=0; i<m_heap.size(); ++i )
|
||||||
|
ostr << i << ": " << m_heap[i] << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void heap_sort( std::vector<T> & v )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
104
labs/priority_queues/test_pq.cpp
Normal file
104
labs/priority_queues/test_pq.cpp
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "priority_queue.h"
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
|
||||||
|
priority_queue<int> pq_int;
|
||||||
|
|
||||||
|
std::cout << "****************\n"
|
||||||
|
<< "* Checkpoint 1 *\n"
|
||||||
|
<< "****************" << std::endl;
|
||||||
|
|
||||||
|
std::vector<int> heap_vector, empty_vector, one_vector;
|
||||||
|
one_vector.push_back( 4 );
|
||||||
|
heap_vector.push_back( 2); heap_vector.push_back(11); heap_vector.push_back( 7);
|
||||||
|
heap_vector.push_back(13); heap_vector.push_back(29); heap_vector.push_back( 8);
|
||||||
|
heap_vector.push_back( 9); heap_vector.push_back(27); heap_vector.push_back(21);
|
||||||
|
heap_vector.push_back(37); heap_vector.push_back(40); heap_vector.push_back(16);
|
||||||
|
std::vector<int> non_heap_vector( heap_vector );
|
||||||
|
non_heap_vector[5] = 23; // less than its parent
|
||||||
|
|
||||||
|
std::cout << "Testing if check_heap works." << std::endl
|
||||||
|
<< "An empty vector is a heap. check_heap = " << pq_int.check_heap(empty_vector) << std::endl
|
||||||
|
<< "A one-element vector is also a heap. check_heap = "
|
||||||
|
<< pq_int.check_heap(one_vector) << std::endl
|
||||||
|
<< "A manually constructed heap. check_heap = " << pq_int.check_heap(heap_vector) << std::endl
|
||||||
|
<< "A change at one location creates a non-heap. check_heap = "
|
||||||
|
<< pq_int.check_heap(non_heap_vector) << std::endl;
|
||||||
|
|
||||||
|
pq_int.push( 5 );
|
||||||
|
pq_int.push( 13 );
|
||||||
|
pq_int.push( 3 );
|
||||||
|
pq_int.push( 11 );
|
||||||
|
pq_int.push( 6 );
|
||||||
|
pq_int.push( 23 );
|
||||||
|
pq_int.push( 8 );
|
||||||
|
pq_int.push( 12 );
|
||||||
|
|
||||||
|
std::cout << "After 8 push operations the size is " << pq_int.size() << std::endl
|
||||||
|
<< "The top, which should be 3, is " << pq_int.top() << std::endl
|
||||||
|
<< "The call to pq.int.empty() returns " << pq_int.empty() << std::endl
|
||||||
|
<< "pq_int.check_heap() = " << pq_int.check_heap() << std::endl;
|
||||||
|
|
||||||
|
std::cout << "\nHere is the actual heap. Values should be 3, 6, 5, 12, 11, 23, 8, 13\n";
|
||||||
|
pq_int.print_heap( std::cout );
|
||||||
|
|
||||||
|
/*
|
||||||
|
std::cout << "\n\n"
|
||||||
|
<< "****************\n"
|
||||||
|
<< "* Checkpoint 2 *\n"
|
||||||
|
<< "****************" << std::endl;
|
||||||
|
|
||||||
|
pq_int.pop();
|
||||||
|
std::cout << "After one pop, the size should be 7. It is " << pq_int.size() << std::endl
|
||||||
|
<< "and the top value should be 5. It is " << pq_int.top() << std::endl;
|
||||||
|
pq_int.pop(); pq_int.pop();
|
||||||
|
std::cout << "After two more pops, the size should be 5. It is " << pq_int.size() << std::endl
|
||||||
|
<< "and the top value should be 8. It is " << pq_int.top() << std::endl;
|
||||||
|
pq_int.push( 1 );
|
||||||
|
std::cout << "Another push should make the top value 1. It is " << pq_int.top() << std::endl;
|
||||||
|
pq_int.pop(); pq_int.pop(); pq_int.pop(); pq_int.pop(); pq_int.pop(); pq_int.pop();
|
||||||
|
std::cout << "After six more pops, the pq should be empty. pq_int.empty() = " << pq_int.empty() << std::endl;
|
||||||
|
|
||||||
|
std::vector<float> v;
|
||||||
|
priority_queue<float> pq_f(v);
|
||||||
|
std::cout << '\n' << "Now we are trying construction from a vector.\n"
|
||||||
|
<< "When the vector is empty, here is the value of pq_f.empty() = " << pq_f.empty() << std::endl;
|
||||||
|
|
||||||
|
v.push_back(13.5); v.push_back(11.1); v.push_back(11.1); v.push_back(-4);
|
||||||
|
v.push_back(14.3); v.push_back(4.5); v.push_back(8.5); v.push_back(27.6);
|
||||||
|
v.push_back(2.3); v.push_back(15.2); v.push_back(23.1); v.push_back(12.5);
|
||||||
|
priority_queue<float> pq_float(v);
|
||||||
|
std::cout << "After constructing from a 12-value vector, the size is " << pq_float.size() << std::endl
|
||||||
|
<< "the top, which should be -4 is " << pq_float.top() << std::endl
|
||||||
|
<< "and check_heap returns " << pq_float.check_heap() << std::endl;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
std::cout << "\n\n"
|
||||||
|
<< "****************\n"
|
||||||
|
<< "* Checkpoint 3 *\n"
|
||||||
|
<< "****************" << std::endl;
|
||||||
|
|
||||||
|
heap_sort( v );
|
||||||
|
int order_errors = 0;
|
||||||
|
for ( unsigned int i=0; i<v.size()-1; ++i )
|
||||||
|
if ( v[i] > v[i+1] ) order_errors ++ ;
|
||||||
|
|
||||||
|
std::cout << "After running heap sort, the size of the vector, which still should be 12 is " << v.size()
|
||||||
|
<< "\nand there are " << order_errors << " ordering errors\n"
|
||||||
|
<< "The resulting vector is\n";
|
||||||
|
for ( unsigned int i=0; i<v.size(); ++i )
|
||||||
|
std::cout << i << ": " << v[i] << '\n';
|
||||||
|
|
||||||
|
std::cout << "\nRunning heap sort on an empty vector... " << std::endl;
|
||||||
|
v.clear();
|
||||||
|
heap_sort(v);
|
||||||
|
std::cout << "produces a vector that is " << (v.empty() ? "empty" : "NOT empty") << std::endl;
|
||||||
|
*/
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -112,7 +112,102 @@ organized heap data, but incur a O(n log n) cost. Why?
|
|||||||
|
|
||||||
- Heap Sort is a simple algorithm to sort a vector of values: Build a heap and then run n consecutive pop operations, storing each “popped” value in a new vector.
|
- Heap Sort is a simple algorithm to sort a vector of values: Build a heap and then run n consecutive pop operations, storing each “popped” value in a new vector.
|
||||||
- It is straightforward to show that this requires O(n log n) time.
|
- It is straightforward to show that this requires O(n log n) time.
|
||||||
- Exercise: Implement an in-place heap sort. An in-place algorithm uses only the memory holding the input data – a separate large temporary vector is not needed.
|
- Heap sort is an in-place sort. An in-place algorithm uses only the memory holding the input data – a separate large temporary vector is not needed.
|
||||||
|
- The following is the sort algorithm with a main function to test it; the code makes a min heap.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
/* The heapify function is designed to ensure that a subtree rooted at a given index i
|
||||||
|
* in an array representation of a min heap maintains the heap property.
|
||||||
|
*
|
||||||
|
* Why Not Just Heapify Once? A single call to heapify on the entire array
|
||||||
|
* wouldn't suffice because heapify is designed to correct violations of
|
||||||
|
* the heap property starting from a specific node, assuming its subtrees are already heaps.
|
||||||
|
* Initially, the array doesn't have this structure, so multiple calls are necessary to build the initial min-heap.
|
||||||
|
* Similarly, during the sorting phase, each extraction disrupts the heap structure, necessitating a call to heapify to restore order.
|
||||||
|
*/
|
||||||
|
void heapify(std::vector<int>& nums, int n, int i){
|
||||||
|
int smallest = i; // assuming i is the smallest
|
||||||
|
int left = 2*i+1; // i's left child is at this location
|
||||||
|
int right = 2*i+2; // i's right child is at this location
|
||||||
|
|
||||||
|
if(left<n && nums[left]<nums[smallest]){
|
||||||
|
smallest = left;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(right<n && nums[right]<nums[smallest]){
|
||||||
|
smallest = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
// after the above, smallest basically will either stay the same, or will be either left or right, depending on nums[left] is larger or nums[right] is larger. largest stays the same if it is already larger than its two children.
|
||||||
|
// if largest is changed, then we do need to swap.
|
||||||
|
if(smallest != i){
|
||||||
|
std::swap(nums[i], nums[smallest]);
|
||||||
|
heapify(nums, n, smallest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// heap sort: O(nlogn)
|
||||||
|
std::vector<int> sortArray(std::vector<int>& nums) {
|
||||||
|
int n = nums.size();
|
||||||
|
// build the heap, starting from the last non-leaf node.
|
||||||
|
// why we start from the last non-leaf node? because leaf nodes inherently satisfy the heap property, as they have no children.
|
||||||
|
// By beginning the heapify process from the last non-leaf node and moving upwards:
|
||||||
|
// We ensure that when we heapify a node, its children are already heapified.
|
||||||
|
// This bottom-up approach guarantees that each subtree satisfies the heap property before moving to the next node.
|
||||||
|
for(int i=n/2-1; i>=0; i--){
|
||||||
|
// heapify the subtree whose root is at i
|
||||||
|
// i.e., build a min heap, with i being the root; and this heap contains nodes from i to n-1;
|
||||||
|
heapify(nums, n, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// now the first one is the largest, swap it to the back
|
||||||
|
// do this n-1 times.
|
||||||
|
for(int i=0; i<(n-1); i++){
|
||||||
|
// build the min heap again, with 0 being the root.
|
||||||
|
// but only consider n-1-i elements, as the others are already in the right place.
|
||||||
|
heapify(nums, n-1-i, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nums;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assuming the heapify and sortArray functions are defined above or included from another file
|
||||||
|
int main() {
|
||||||
|
// Sample data to be sorted
|
||||||
|
std::vector<int> nums = {42, 12, 13, 65, 98, 45, 97, 85, 76, 90};
|
||||||
|
|
||||||
|
// Output the original array
|
||||||
|
std::cout << "Original array:\n";
|
||||||
|
for (int num : nums) {
|
||||||
|
std::cout << num << " ";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
// Sort the array using your sortArray function
|
||||||
|
std::vector<int> sortedNums = sortArray(nums);
|
||||||
|
|
||||||
|
// Output the sorted array
|
||||||
|
std::cout << "\nSorted array:\n";
|
||||||
|
for (int num : sortedNums) {
|
||||||
|
std::cout << num << " ";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The above program prints the following:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ g++ heap_sort.cpp
|
||||||
|
$ ./a.out
|
||||||
|
Original array:
|
||||||
|
42 12 13 65 98 45 97 85 76 90
|
||||||
|
|
||||||
|
Sorted array:
|
||||||
|
12 42 13 65 90 45 97 85 76 98
|
||||||
|
```
|
||||||
|
|
||||||
## 24.9 Summary Notes about Vector-Based Priority Queues
|
## 24.9 Summary Notes about Vector-Based Priority Queues
|
||||||
|
|
||||||
@@ -122,8 +217,10 @@ organized heap data, but incur a O(n log n) cost. Why?
|
|||||||
|
|
||||||
## 24.10 Leetcode Exercises
|
## 24.10 Leetcode Exercises
|
||||||
|
|
||||||
|
In addition to the above solution, there are also other variations of the heap sort:
|
||||||
|
|
||||||
- [Leetcode problem 912: Sort an Array](https://leetcode.com/problems/sort-an-array/).
|
- [Leetcode problem 912: Sort an Array](https://leetcode.com/problems/sort-an-array/).
|
||||||
- Solution: [p912_heapsort_array.cpp](../../leetcode/p912_heapsort_array.cpp).
|
- Solution: [p912_heapsort_array.cpp](../../leetcode/p912_heapsort_array.cpp).
|
||||||
- Solution 2: [p912_heapsort_array_heapify.cpp](../../leetcode/p912_heapsort_array_heapify.cpp).
|
- Solution 2: - max heap: [p912_heapsort_array_heapify.cpp](../../leetcode/p912_heapsort_array_heapify.cpp).
|
||||||
- Solution 3: - min heap: [p912_heapsort_array_min_heap.cpp](../../leetcode/p912_heapsort_array_min_heap.cpp).
|
- Solution 3: - min heap: [p912_heapsort_array_min_heap.cpp](../../leetcode/p912_heapsort_array_min_heap.cpp).
|
||||||
- Solution 4: - min heap, with functor: [p912_heapsort_array_functor.cpp](../../leetcode/p912_heapsort_array_functor.cpp).
|
- Solution 4: - min heap, with functor: [p912_heapsort_array_functor.cpp](../../leetcode/p912_heapsort_array_functor.cpp).
|
||||||
|
|||||||
101
lectures/24_priority_queues_II/heap_sort.cpp
Normal file
101
lectures/24_priority_queues_II/heap_sort.cpp
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/* The heapify function is designed to ensure that a subtree rooted at a given index i
|
||||||
|
* in an array representation of a heap maintains the heap property.
|
||||||
|
* While the function doesn't have an explicit base case like some recursive functions,
|
||||||
|
* it inherently terminates due to the following conditions:
|
||||||
|
*
|
||||||
|
* Leaf Node Condition: If the node at index i is a leaf node (i.e., it has no children),
|
||||||
|
* the function reaches a point where both left and right indices are greater than or equal to n (the size of the heap).
|
||||||
|
* In this scenario, the conditions left < n and right < n in the if statements evaluating the children will both be false,
|
||||||
|
* preventing further recursive calls.
|
||||||
|
*
|
||||||
|
* Heap Property Satisfaction: If the node at index i is greater than or equal to its children (or if it has no children),
|
||||||
|
* the heap property is already satisfied. Consequently, the variable largest remains equal to i,
|
||||||
|
* and the condition largest != i evaluates to false.
|
||||||
|
* This prevents the swap operation and the subsequent recursive call, leading to termination.
|
||||||
|
* In essence, the function will return when:
|
||||||
|
* The node is a leaf node.
|
||||||
|
* The node's value is greater than or equal to its children's values, maintaining the heap property.
|
||||||
|
* These implicit conditions ensure that the recursion does not continue indefinitely.
|
||||||
|
*
|
||||||
|
* Why Not Just Heapify Once? A single call to heapify on the entire array
|
||||||
|
* wouldn't suffice because heapify is designed to correct violations of
|
||||||
|
* the heap property starting from a specific node, assuming its subtrees are already heaps.
|
||||||
|
* Initially, the array doesn't have this structure, so multiple calls are necessary to build the initial max-heap.
|
||||||
|
* Similarly, during the sorting phase, each extraction disrupts the heap structure, necessitating a call to heapify to restore order.
|
||||||
|
* */
|
||||||
|
|
||||||
|
void heapify(std::vector<int>& nums, int n, int i){
|
||||||
|
int smallest = i; // assuming i is the smallest
|
||||||
|
int left = 2*i+1; // i's left child is at this location
|
||||||
|
int right = 2*i+2; // i's right child is at this location
|
||||||
|
|
||||||
|
if(left<n && nums[left]<nums[smallest]){
|
||||||
|
smallest = left;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(right<n && nums[right]<nums[smallest]){
|
||||||
|
smallest = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
// after the above, smallest basically will either stay the same, or will be either left or right, depending on nums[left] is larger or nums[right] is larger. largest stays the same if it is already larger than its two children.
|
||||||
|
// if largest is changed, then we do need to swap.
|
||||||
|
if(smallest != i){
|
||||||
|
std::swap(nums[i], nums[smallest]);
|
||||||
|
heapify(nums, n, smallest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// heap sort: O(nlogn)
|
||||||
|
std::vector<int> sortArray(std::vector<int>& nums) {
|
||||||
|
int n = nums.size();
|
||||||
|
// build the heap, starting from the last non-leaf node.
|
||||||
|
// why we start from the last non-leaf node? because leaf nodes inherently satisfy the heap property, as they have no children.
|
||||||
|
// By beginning the heapify process from the last non-leaf node and moving upwards:
|
||||||
|
// We ensure that when we heapify a node, its children are already heapified.
|
||||||
|
// This bottom-up approach guarantees that each subtree satisfies the heap property before moving to the next node.
|
||||||
|
for(int i=n/2-1; i>=0; i--){
|
||||||
|
// heapify the subtree whose root is at i
|
||||||
|
// i.e., build a max heap, with i being the root; and this heap contains nodes from i to n-1;
|
||||||
|
heapify(nums, n, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// now the first one is the largest, swap it to the back
|
||||||
|
// do this n-1 times.
|
||||||
|
for(int i=0; i<(n-1); i++){
|
||||||
|
// nums[0] is always the largest one
|
||||||
|
std::swap(nums[0], nums[n-1-i]);
|
||||||
|
// build the max heap again, with 0 being the root.
|
||||||
|
// but only consider n-1-i elements, as the others are already in the right place.
|
||||||
|
heapify(nums, n-1-i, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nums;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assuming the heapify and sortArray functions are defined above or included from another file
|
||||||
|
int main() {
|
||||||
|
// Sample data to be sorted
|
||||||
|
std::vector<int> nums = {42, 12, 13, 65, 98, 45, 97, 85, 76, 90};
|
||||||
|
|
||||||
|
// Output the original array
|
||||||
|
std::cout << "Original array:\n";
|
||||||
|
for (int num : nums) {
|
||||||
|
std::cout << num << " ";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
// Sort the array using your sortArray function
|
||||||
|
std::vector<int> sortedNums = sortArray(nums);
|
||||||
|
|
||||||
|
// Output the sorted array
|
||||||
|
std::cout << "\nSorted array:\n";
|
||||||
|
for (int num : sortedNums) {
|
||||||
|
std::cout << num << " ";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,5 +1,24 @@
|
|||||||
class Solution {
|
class Solution {
|
||||||
public:
|
public:
|
||||||
|
/* The heapify function is designed to ensure that a subtree rooted at a given index i
|
||||||
|
* in an array representation of a heap maintains the heap property.
|
||||||
|
* While the function doesn't have an explicit base case like some recursive functions,
|
||||||
|
* it inherently terminates due to the following conditions:
|
||||||
|
*
|
||||||
|
* Leaf Node Condition: If the node at index i is a leaf node (i.e., it has no children),
|
||||||
|
* the function reaches a point where both left and right indices are greater than or equal to n (the size of the heap).
|
||||||
|
* In this scenario, the conditions left < n and right < n in the if statements evaluating the children will both be false,
|
||||||
|
* preventing further recursive calls.
|
||||||
|
*
|
||||||
|
* Heap Property Satisfaction: If the node at index i is greater than or equal to its children (or if it has no children),
|
||||||
|
* the heap property is already satisfied. Consequently, the variable largest remains equal to i,
|
||||||
|
* and the condition largest != i evaluates to false.
|
||||||
|
* This prevents the swap operation and the subsequent recursive call, leading to termination.
|
||||||
|
* In essence, the function will return when:
|
||||||
|
* The node is a leaf node.
|
||||||
|
* The node's value is greater than or equal to its children's values, maintaining the heap property.
|
||||||
|
* These implicit conditions ensure that the recursion does not continue indefinitely.
|
||||||
|
* */
|
||||||
void heapify(vector<int>& nums, int n, int i){
|
void heapify(vector<int>& nums, int n, int i){
|
||||||
int largest = i; // assuming i is the largest
|
int largest = i; // assuming i is the largest
|
||||||
int left = 2*i+1; // i's left child is at this location
|
int left = 2*i+1; // i's left child is at this location
|
||||||
@@ -24,10 +43,14 @@ public:
|
|||||||
// heap sort: O(nlogn)
|
// heap sort: O(nlogn)
|
||||||
vector<int> sortArray(vector<int>& nums) {
|
vector<int> sortArray(vector<int>& nums) {
|
||||||
int n = nums.size();
|
int n = nums.size();
|
||||||
// build the heap, starting from the last non-leaf node
|
// build the heap, starting from the last non-leaf node.
|
||||||
|
// why we start from the last non-leaf node? because leaf nodes inherently satisfy the heap property, as they have no children.
|
||||||
|
// By beginning the heapify process from the last non-leaf node and moving upwards:
|
||||||
|
// We ensure that when we heapify a node, its children are already heapified.
|
||||||
|
// This bottom-up approach guarantees that each subtree satisfies the heap property before moving to the next node.
|
||||||
for(int i=n/2-1; i>=0; i--){
|
for(int i=n/2-1; i>=0; i--){
|
||||||
// heapify the subtree whose root is at i
|
// heapify the subtree whose root is at i
|
||||||
// i.e., build a max heap, with i being the root.
|
// i.e., build a max heap, with i being the root; and this heap contains nodes from i to n-1;
|
||||||
heapify(nums, n, i);
|
heapify(nums, n, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user