Add old works for Algorithms and Data Structeres
This commit is contained in:
@@ -0,0 +1 @@
|
||||
/target
|
||||
Generated
+7
@@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "array_list"
|
||||
version = "0.1.0"
|
||||
@@ -0,0 +1,4 @@
|
||||
[package]
|
||||
name = "array_list"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
@@ -0,0 +1,125 @@
|
||||
# Array List
|
||||
|
||||
Implements a custom dynamic array (similar to a standard Vector) that manually manages memory allocation and resizing. It includes built-in Binary Heap logic to perform in-place Heapsort and priority-queue operations (like deleting the top element). It also features a utility to visualize the array's internal structure as a printed ASCII tree.
|
||||
|
||||
Execution result:
|
||||
```
|
||||
Data unsorted: [0, 1, 4, 9, 16, 25, 36, 0, 8, 18, 30, 44, 60, 78, 0, 15, 32, 51, 72, 95, 120, 0, 22, 46, 72, 100, 130, 162, 0, 29, 60, 93]
|
||||
┌ 93
|
||||
┌ 15
|
||||
┌ 0
|
||||
│ └ 32
|
||||
┌ 9
|
||||
│ │ ┌ 51
|
||||
│ └ 8
|
||||
│ └ 72
|
||||
┌ 1
|
||||
│ │ ┌ 95
|
||||
│ │ ┌ 18
|
||||
│ │ │ └ 120
|
||||
│ └ 16
|
||||
│ │ ┌ 0
|
||||
│ └ 30
|
||||
│ └ 22
|
||||
0
|
||||
│ ┌ 46
|
||||
│ ┌ 44
|
||||
│ │ └ 72
|
||||
│ ┌ 25
|
||||
│ │ │ ┌ 100
|
||||
│ │ └ 60
|
||||
│ │ └ 130
|
||||
└ 4
|
||||
│ ┌ 162
|
||||
│ ┌ 78
|
||||
│ │ └ 0
|
||||
└ 36
|
||||
│ ┌ 29
|
||||
└ 0
|
||||
└ 60
|
||||
|
||||
Data ascending: [0, 0, 0, 0, 0, 1, 4, 8, 9, 15, 16, 18, 22, 25, 29, 30, 32, 36, 44, 46, 51, 60, 60, 72, 72, 78, 93, 95, 100, 120, 130, 162]
|
||||
┌ 162
|
||||
┌ 30
|
||||
┌ 8
|
||||
│ └ 32
|
||||
┌ 0
|
||||
│ │ ┌ 36
|
||||
│ └ 9
|
||||
│ └ 44
|
||||
┌ 0
|
||||
│ │ ┌ 46
|
||||
│ │ ┌ 15
|
||||
│ │ │ └ 51
|
||||
│ └ 0
|
||||
│ │ ┌ 60
|
||||
│ └ 16
|
||||
│ └ 60
|
||||
0
|
||||
│ ┌ 72
|
||||
│ ┌ 18
|
||||
│ │ └ 72
|
||||
│ ┌ 1
|
||||
│ │ │ ┌ 78
|
||||
│ │ └ 22
|
||||
│ │ └ 93
|
||||
└ 0
|
||||
│ ┌ 95
|
||||
│ ┌ 25
|
||||
│ │ └ 100
|
||||
└ 4
|
||||
│ ┌ 120
|
||||
└ 29
|
||||
└ 130
|
||||
|
||||
Data descending: [162, 130, 120, 100, 95, 93, 78, 72, 72, 60, 60, 51, 46, 44, 36, 32, 30, 29, 25, 22, 18, 16, 15, 9, 8, 4, 1, 0, 0, 0, 0, 0]
|
||||
┌ 0
|
||||
┌ 32
|
||||
┌ 72
|
||||
│ └ 30
|
||||
┌ 100
|
||||
│ │ ┌ 29
|
||||
│ └ 72
|
||||
│ └ 25
|
||||
┌ 130
|
||||
│ │ ┌ 22
|
||||
│ │ ┌ 60
|
||||
│ │ │ └ 18
|
||||
│ └ 95
|
||||
│ │ ┌ 16
|
||||
│ └ 60
|
||||
│ └ 15
|
||||
162
|
||||
│ ┌ 9
|
||||
│ ┌ 51
|
||||
│ │ └ 8
|
||||
│ ┌ 93
|
||||
│ │ │ ┌ 4
|
||||
│ │ └ 46
|
||||
│ │ └ 1
|
||||
└ 120
|
||||
│ ┌ 0
|
||||
│ ┌ 44
|
||||
│ │ └ 0
|
||||
└ 78
|
||||
│ ┌ 0
|
||||
└ 36
|
||||
└ 0
|
||||
|
||||
|
||||
Data [1, 12, 9, 5, 6, 10]
|
||||
┌ 5
|
||||
┌ 12
|
||||
│ └ 6
|
||||
1
|
||||
│ ┌ 10
|
||||
└ 9
|
||||
Deleting top: Some(12)
|
||||
┌ 5
|
||||
┌ 6
|
||||
│ └ 1
|
||||
10
|
||||
└ 9
|
||||
|
||||
Deleting top with one element: None
|
||||
```
|
||||
@@ -0,0 +1,202 @@
|
||||
#[derive(Default)]
|
||||
struct ArrayList {
|
||||
length: usize,
|
||||
allocate: usize,
|
||||
capacity: usize,
|
||||
data: Box<[i32]>,
|
||||
}
|
||||
|
||||
impl ArrayList {
|
||||
const fn len(&self) -> usize {
|
||||
self.length
|
||||
}
|
||||
|
||||
const fn capacity(&self) -> usize {
|
||||
self.capacity
|
||||
}
|
||||
|
||||
const fn is_empty(&self) -> bool {
|
||||
self.length == 0
|
||||
}
|
||||
|
||||
const fn is_full(&self) -> bool {
|
||||
self.length == self.capacity
|
||||
}
|
||||
}
|
||||
|
||||
impl ArrayList {
|
||||
fn alloc(size: usize) -> Box<[i32]> {
|
||||
vec![0i32; size].into_boxed_slice()
|
||||
}
|
||||
|
||||
fn change_capacity(&mut self, size: usize) {
|
||||
self.capacity = size;
|
||||
let old_data = std::mem::replace(&mut self.data, Self::alloc(size));
|
||||
self.data[..self.length].copy_from_slice(&old_data[..self.length]);
|
||||
}
|
||||
|
||||
pub fn new(allocate: usize) -> Self {
|
||||
assert!(allocate > 0);
|
||||
|
||||
Self {
|
||||
allocate,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push(&mut self, num: i32) {
|
||||
if self.is_full() {
|
||||
self.change_capacity(self.capacity + self.allocate);
|
||||
}
|
||||
|
||||
self.data[self.length] = num;
|
||||
self.length += 1;
|
||||
}
|
||||
|
||||
pub fn pop(&mut self) -> Option<i32> {
|
||||
if self.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
self.length -= 1;
|
||||
Some(self.data[self.length])
|
||||
}
|
||||
|
||||
pub fn shrink(&mut self) {
|
||||
self.change_capacity(self.length);
|
||||
}
|
||||
|
||||
pub fn slice(&self) -> &[i32] {
|
||||
&self.data[..self.length]
|
||||
}
|
||||
|
||||
fn heapify(&mut self, idx: usize, len: usize, max_heap: bool) {
|
||||
if idx >= len {
|
||||
return;
|
||||
}
|
||||
|
||||
let idxs = [idx, 2 * idx + 1, 2 * idx + 2]
|
||||
.into_iter()
|
||||
.filter(|&i| i < len);
|
||||
|
||||
let swap_idx = if max_heap {
|
||||
idxs.max_by_key(|&i| self.data[i])
|
||||
} else {
|
||||
idxs.min_by_key(|&i| self.data[i])
|
||||
}
|
||||
.unwrap();
|
||||
|
||||
if swap_idx != idx {
|
||||
self.data.swap(swap_idx, idx);
|
||||
self.heapify(swap_idx, len, max_heap);
|
||||
}
|
||||
}
|
||||
|
||||
fn make_heap(&mut self, max_heap: bool) {
|
||||
// parent of last element (last_idx-1)/2 or (len/2)-1
|
||||
for idx in (0..self.length / 2).rev() {
|
||||
self.heapify(idx, self.length, max_heap);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sort(&mut self, ascending: bool) {
|
||||
self.make_heap(ascending);
|
||||
|
||||
for len in (1..self.length).rev() {
|
||||
self.data.swap(0, len);
|
||||
self.heapify(0, len, ascending);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delete_top(&mut self) -> Option<i32> {
|
||||
if self.is_empty() {
|
||||
return None;
|
||||
}
|
||||
if self.length == 1 {
|
||||
return self.pop();
|
||||
}
|
||||
|
||||
self.make_heap(true);
|
||||
self.length -= 1;
|
||||
self.data.swap(0, self.length);
|
||||
self.heapify(0, self.length, true);
|
||||
|
||||
Some(self.data[self.length])
|
||||
}
|
||||
|
||||
fn tree_internal(&self, idx: usize, lines: Vec<&str>, dir: i8) {
|
||||
if 2 * idx + 1 < self.length {
|
||||
let mut l = lines.clone();
|
||||
if dir == 1 {
|
||||
l.pop();
|
||||
l.push(" ");
|
||||
}
|
||||
l.push("│");
|
||||
self.tree_internal(2 * idx + 1, l, 1);
|
||||
}
|
||||
|
||||
let mut l = lines.clone();
|
||||
l.pop();
|
||||
l.push(["└ ", "", "┌ "][(dir + 1) as usize]);
|
||||
println!("{}{}", l.join(" "), self.data[idx]);
|
||||
|
||||
if 2 * idx + 2 < self.length {
|
||||
let mut l = lines;
|
||||
if dir == -1 {
|
||||
l.pop();
|
||||
l.push(" ");
|
||||
}
|
||||
l.push("│");
|
||||
self.tree_internal(2 * idx + 2, l, -1);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tree(&self) {
|
||||
self.tree_internal(0, vec![], 0);
|
||||
}
|
||||
}
|
||||
|
||||
use std::fmt;
|
||||
impl fmt::Display for ArrayList {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", &self.data[..self.length])
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut arr = ArrayList::new(10);
|
||||
for i in 0..32 {
|
||||
arr.push(i % 7 * i);
|
||||
}
|
||||
|
||||
println!("Data unsorted: {arr}");
|
||||
arr.tree();
|
||||
println!();
|
||||
|
||||
arr.sort(true);
|
||||
println!("Data ascending: {arr}");
|
||||
arr.tree();
|
||||
println!();
|
||||
|
||||
arr.sort(false);
|
||||
println!("Data descending: {arr}");
|
||||
arr.tree();
|
||||
println!();
|
||||
|
||||
let mut arr = ArrayList::new(10);
|
||||
for i in [1, 12, 9, 5, 6, 10] {
|
||||
arr.push(i);
|
||||
}
|
||||
|
||||
println!();
|
||||
println!("Data {arr}");
|
||||
arr.tree();
|
||||
println!("Deleting top: {:?}", arr.delete_top());
|
||||
arr.tree();
|
||||
|
||||
println!();
|
||||
println!(
|
||||
"Deleting top with one element: {:?}",
|
||||
ArrayList::new(5).delete_top()
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user