Snyggade till README
This commit is contained in:
116
README.md
116
README.md
@@ -4,145 +4,49 @@ Ett enkelt projekt som implementerar ett **binärt sökträd (BST)** i C++. Kode
|
|||||||
|
|
||||||
> **Notera:** I den kod som följde med finns referenser till `defs.h` samt typerna `dataType`, `ptrType` och klassen/structen `treeNode` som **inte** följde med i uppladdningen. README:n nedan utgår från hur gränssnittet ser ut i `tree.h`/`tree.cpp` och beskriver hur du kan komplettera.
|
> **Notera:** I den kod som följde med finns referenser till `defs.h` samt typerna `dataType`, `ptrType` och klassen/structen `treeNode` som **inte** följde med i uppladdningen. README:n nedan utgår från hur gränssnittet ser ut i `tree.h`/`tree.cpp` och beskriver hur du kan komplettera.
|
||||||
|
|
||||||
## Filstruktur
|
|
||||||
```
|
|
||||||
.
|
|
||||||
├── tree.h
|
|
||||||
└── tree.cpp
|
|
||||||
```
|
|
||||||
|
|
||||||
### `tree.h`
|
### `tree.h`
|
||||||
|
|
||||||
Deklarerar klassen `treeClass` med:
|
Deklarerar klassen `treeClass` med:
|
||||||
|
|
||||||
- `ptrType root` – pekare till rotnoden
|
- `ptrType root` – pekare till rotnoden
|
||||||
- `seek`, `insert`, `del`, `delRoot`, `delLeft` – kärnoperationer
|
- `seek`, `insert`, `del`, `delRoot`, `delLeft` – kärnoperationer
|
||||||
- Traversering: `preOrder`, `inOrder`, `postOrder`
|
- Traversering: `preOrder`, `inOrder`, `postOrder`
|
||||||
- `save` – skriver trädets noder till en ström
|
- `save` – skriver trädets noder till en ström
|
||||||
|
|
||||||
### `tree.cpp`
|
### `tree.cpp`
|
||||||
|
|
||||||
Definitioner för metoderna ovan. Använder `defs.h`, `dataType`, `ptrType` och `treeNode`:
|
Definitioner för metoderna ovan. Använder `defs.h`, `dataType`, `ptrType` och `treeNode`:
|
||||||
|
|
||||||
- `treeNode` förväntas vara en nod med fälten `data`, `left`, `right`.
|
- `treeNode` förväntas vara en nod med fälten `data`, `left`, `right`.
|
||||||
- `dataType` är datatypen som lagras i trädet (t.ex. `int` eller en struct med jämförelseoperatorer).
|
- `dataType` är datatypen som lagras i trädet (t.ex. `int` eller en struct med jämförelseoperatorer).
|
||||||
- `ptrType` är sannolikt `treeNode*`.
|
- `ptrType` är sannolikt `treeNode*`.
|
||||||
|
|
||||||
## Förslag på kompletterande definitioner (`defs.h`)
|
|
||||||
Skapa en enkel header så att projektet kompilerar. Exempel med heltal:
|
|
||||||
```cpp
|
|
||||||
// defs.h
|
|
||||||
#pragma once
|
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
typedef int dataType;
|
|
||||||
|
|
||||||
struct treeNode {
|
|
||||||
dataType data;
|
|
||||||
treeNode* left;
|
|
||||||
treeNode* right;
|
|
||||||
treeNode(dataType d, treeNode* L=nullptr, treeNode* R=nullptr)
|
|
||||||
: data(d), left(L), right(R) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
using ptrType = treeNode*;
|
|
||||||
|
|
||||||
#ifndef TRUE
|
|
||||||
#define TRUE true
|
|
||||||
#endif
|
|
||||||
#ifndef FALSE
|
|
||||||
#define FALSE false
|
|
||||||
#endif
|
|
||||||
```
|
|
||||||
> I din `tree.cpp` finns redan en *medlemskonstruktör* för `treeNode` (`treeNode::treeNode(...)`), så du kan antingen:
|
|
||||||
> 1) Låta konstruktorn bo i structen som ovan (rekommenderat) **och ta bort** den fristående definitionen i `tree.cpp`, **eller**
|
|
||||||
> 2) Ha endast deklaration i `defs.h` och behålla definitionen i `tree.cpp`.
|
|
||||||
|
|
||||||
## Exempel på `main.cpp`
|
|
||||||
Skapa ett minimalt körbart exempel:
|
|
||||||
```cpp
|
|
||||||
#include <iostream>
|
|
||||||
#include "defs.h"
|
|
||||||
#include "tree.h"
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
treeClass t;
|
|
||||||
|
|
||||||
// Bygg ett litet träd
|
|
||||||
t.insert(t.root, 7);
|
|
||||||
t.insert(t.root, 3);
|
|
||||||
t.insert(t.root, 9);
|
|
||||||
t.insert(t.root, 1);
|
|
||||||
t.insert(t.root, 5);
|
|
||||||
|
|
||||||
std::cout << "Inorder: ";
|
|
||||||
t.inOrder(t.root);
|
|
||||||
std::cout << "\n";
|
|
||||||
|
|
||||||
// Sök
|
|
||||||
auto hit = t.seek(t.root, 5);
|
|
||||||
std::cout << (hit ? "Hittade 5" : "Hittade inte 5") << "\n";
|
|
||||||
|
|
||||||
// Ta bort
|
|
||||||
t.del(t.root, 3);
|
|
||||||
std::cout << "Efter del(3), inorder: ";
|
|
||||||
t.inOrder(t.root);
|
|
||||||
std::cout << "\n";
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Bygga & köra
|
## Bygga & köra
|
||||||
|
|
||||||
### Med g++
|
### Med g++
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
g++ -std=c++17 -O2 -Wall -Wextra -o bst main.cpp tree.cpp
|
g++ -std=c++17 -O2 -Wall -Wextra -o bst main.cpp tree.cpp
|
||||||
./bst
|
./bst
|
||||||
```
|
```
|
||||||
|
|
||||||
### Med CMake (valfritt)
|
|
||||||
Skapa `CMakeLists.txt`:
|
|
||||||
```cmake
|
|
||||||
cmake_minimum_required(VERSION 3.15)
|
|
||||||
project(bst LANGUAGES CXX)
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
|
||||||
add_executable(bst main.cpp tree.cpp)
|
|
||||||
```
|
|
||||||
Sedan:
|
|
||||||
```bash
|
|
||||||
cmake -S . -B build
|
|
||||||
cmake --build build --config Release
|
|
||||||
./build/bst
|
|
||||||
```
|
|
||||||
|
|
||||||
## Traverseringar
|
## Traverseringar
|
||||||
|
|
||||||
- **Pre‑order:** Rot → Vänster → Höger
|
- **Pre‑order:** Rot → Vänster → Höger
|
||||||
- **In‑order:** Vänster → Rot → Höger (ger sorterad ordning för BST)
|
- **In‑order:** Vänster → Rot → Höger (ger sorterad ordning för BST)
|
||||||
- **Post‑order:** Vänster → Höger → Rot
|
- **Post‑order:** Vänster → Höger → Rot
|
||||||
|
|
||||||
## Borttagning (översikt)
|
## Borttagning (översikt)
|
||||||
|
|
||||||
`del` hittar noden att ta bort, `delRoot` hanterar tre fall:
|
`del` hittar noden att ta bort, `delRoot` hanterar tre fall:
|
||||||
|
|
||||||
1. **Bladnod** → delete, sätt pekaren till `nullptr`.
|
1. **Bladnod** → delete, sätt pekaren till `nullptr`.
|
||||||
2. **En ensam höger- eller vänstergren** → flytta upp barnpekaren.
|
2. **En ensam höger- eller vänstergren** → flytta upp barnpekaren.
|
||||||
3. **Två barn** → hämta minsta värdet i höger delträd (via `delLeft`), ersätt data och ta bort den noden.
|
3. **Två barn** → hämta minsta värdet i höger delträd (via `delLeft`), ersätt data och ta bort den noden.
|
||||||
|
|
||||||
## Serialisering (`save`)
|
|
||||||
Metoden `save(ptrType root, std::fstream &fil)` försöker skriva data rekursivt. Just nu används
|
|
||||||
```cpp
|
|
||||||
fil.write((char*)&root->data, sizeof(root));
|
|
||||||
```
|
|
||||||
Detta är sannolikt en **bugg** – `sizeof(root)` är storleken på pekaren, inte på `data`. Ändra till:
|
|
||||||
```cpp
|
|
||||||
fil.write(reinterpret_cast<char*>(&root->data), sizeof(root->data));
|
|
||||||
```
|
|
||||||
Och tänk på **endianess**/typstorlek om filen ska vara portabel. För portabel serialisering, överväg textformat (t.ex. inorder-traversering till text) eller ett binärt, väldefinierat format.
|
|
||||||
|
|
||||||
## Kända förbättringar
|
## Kända förbättringar
|
||||||
|
|
||||||
- **Null‑skydd i `del`**: Kontrollera att `root` inte är `nullptr` innan jämförelser.
|
- **Null‑skydd i `del`**: Kontrollera att `root` inte är `nullptr` innan jämförelser.
|
||||||
- **`isEmpty`** kan returnera `root == nullptr` direkt.
|
- **`isEmpty`** kan returnera `root == nullptr` direkt.
|
||||||
- **Konstkorrekthet**: Markera lämpliga metoder som `const` där möjligt.
|
- **Konstkorrekthet**: Markera lämpliga metoder som `const` där möjligt.
|
||||||
- **Separera I/O**: Låt traversering skriva till en ström (`std::ostream&`) istället för `std::cout` direkt.
|
- **Separera I/O**: Låt traversering skriva till en ström (`std::ostream&`) istället för `std::cout` direkt.
|
||||||
- **Enhetstester**: Lägg till små tester som verifierar `insert/seek/del`.
|
|
||||||
|
|
||||||
## Licens
|
|
||||||
Välj en licens (t.ex. MIT) och lägg i `LICENSE`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Förslag:** Ladda gärna upp `defs.h` (och ev. `main.cpp`) så kan jag uppdatera README och lägga till exakta bygginstruktioner för ditt case.
|
|
||||||
|
|||||||
Reference in New Issue
Block a user