Startpunkten

This commit is contained in:
2026-03-05 13:39:39 +01:00
commit c4d164d8c3
20 changed files with 3598 additions and 0 deletions

292
Hashing/hash.cpp Normal file
View File

@@ -0,0 +1,292 @@
//##################################################################
// PROGRAMMERINGSUPPGIFT 3
// DATASTRUKTURER OCH ALGORITMER
// HASH TABELL
//==================================================================
// HASH.HPP
// Filen innehåller hashfunktionerna
// Christian Ohlsson
// Ingela Johansson
// Anna-Maria Haglund
// Karlstad 981007
//==================================================================
#include "header.hpp"
//##################################################################
//Function: hashClass()
//Task: constuctorn
//Calls: nothing
//==================================================================
hashClass::hashClass()
{
prime();
PRIMENUMBER=0;
ARRAYSIZE = DEFAULTSIZE;
hashPtr = new hashNode[ARRAYSIZE];
for(int i=0; i<ARRAYSIZE ; i++) {
strcpy(hashPtr[i].name, "");
strcpy(hashPtr[i].number, "");
hashPtr[i].exist = FALSE;
}
}
//##################################################################
//Function: ~hashclass
//Task: destructorn
//Calls: nothing
//==================================================================
hashClass::~hashClass(){ delete hashPtr; }
//##################################################################
//Function: getSize()
//Task: returnerar storleken på hashtabellen
//Calls: nothing
//==================================================================
int hashClass::getSize(){ return ARRAYSIZE; }
//##################################################################
//Function: nextPrime()
//Task: returnerar nästa primtal
//Calls: nothing
//==================================================================
int hashClass::nextPrime()
{
PRIMENUMBER++;
return primeArray[DEFAULTPRIMENUMBER+PRIMENUMBER];
}
//##################################################################
//Function: prime()
//Task: lägger in primtalen i en array
//Calls: isPrime()
//==================================================================
void hashClass::prime()
{
int i = 1, num=FIRSTPRIME;
primeArray[0] = STARTPRIME;
while(i<PRIMEARRAYSIZE) {
if(isPrime(num, i, primeArray)) {
primeArray[i] = num;
i++;
}
num = (num+PRIMESTEP);
}
}
//##################################################################
//Function: isPrime()
//Task: kollar om ett tal är ett primtal
//Calls: nothing
//=================================================================
bool hashClass::isPrime(int nummer, int antal, int primeArray[PRIMEARRAYSIZE])
{
for(int i = 0; i < antal; i++)
if(nummer%primeArray[i] == 0)
return FALSE;
return TRUE;
}
//##################################################################
//Function: search()
//Task: söker efter ett namn i tabellen
//Calls: hash1() och hash2()
//==================================================================
bool hashClass::search(nameType name)
{
int location = hash1(name);
if(strcmp(hashPtr[location].name, name) == 0)
return TRUE;
else
while(hashPtr[location].exist == TRUE) {
location = location + hash2(hash1(name));
if(location > ARRAYSIZE)
location = location - ARRAYSIZE;
if(strcmp(hashPtr[location].name, name) == 0)
return TRUE;
}
return FALSE;
}
//##################################################################
//Function: getNode()
//Task: hämtar en nod ur tabellen, d.v.s. namn telefonnummer och
// "deleted-flaggan"
//Calls: hash1() och hash2()
//==================================================================
hashNode hashClass::getNode(nameType &oneName)
{
int location = hash1(oneName);
if(strcmp(hashPtr[location].name, oneName) == 0)
return (hashPtr[location]);
else
do {
location = location + hash2(hash1(oneName));
if(location>ARRAYSIZE) {
location = (location-ARRAYSIZE);
if(strcmp(hashPtr[location].name, oneName) == 0)
return hashPtr[location];
}
}while(hashPtr[location].exist == FALSE);
}
//##################################################################
//Function: biggerHash()
//Task: kollar om en större tabell behövs (om 80% av positionerna
// är upptagna)
//Calls: checkOccupied()
//==================================================================
bool hashClass::biggerHash()
{
float siz = INSERTFACTOR*getSize();
int occ = checkOccupied();
if(occ>=siz)
return TRUE;
return FALSE;
}
//##################################################################
//Function: newHashArray()
//Task:
//Calls: reHash()
//==================================================================
void hashClass::newHashArray()
{
int oldSize = ARRAYSIZE;
ARRAYSIZE = nextPrime();
reHash(oldSize);
}
//##################################################################
//Function:
//Task:
//Calls:
//==================================================================
bool hashClass::anotherHash()
{
int del=0;
float siz = DELETEFACTOR*getSize();
for(int i=0; i<ARRAYSIZE ; i++)
if(hashPtr[i].exist == TRUE && !hashPtr[i].name[0])
del++;
if(del>=siz)
return TRUE;
return FALSE;
}
//##################################################################
//Function:
//Task:
//Calls:
//==================================================================
void hashClass::reHash(int oldSize)
{
int location;
hashNode *tempPtr = new hashNode[ARRAYSIZE];
for(int j=0; j<oldSize ; j++) {
strcpy(tempPtr[j].name, hashPtr[j].name);
strcpy(tempPtr[j].number, hashPtr[j].number);
tempPtr[j].exist = hashPtr[j].exist;
}
destroyHash(oldSize);
hashPtr = new hashNode[ARRAYSIZE];
for(int k=0; k<ARRAYSIZE ; k++) {
strcpy(hashPtr[k].name, "");
strcpy(hashPtr[k].number, "");
hashPtr[k].exist = FALSE;
}
for(int i=0; i<oldSize ; i++)
if(tempPtr[i].exist == TRUE && tempPtr[i].name[0]) {
location = hash1(tempPtr[i].name);
if(hashPtr[location].exist == FALSE)
insert(location, tempPtr[i]);
else
while(hashPtr[location].exist == TRUE) {
location = location + hash2(hash1(tempPtr[i].name));
if(location > ARRAYSIZE)
location = location - ARRAYSIZE;
if(hashPtr[location].exist == FALSE)
insert(location, tempPtr[i]);
}
}
delete tempPtr;
}
//##################################################################
//Function:
//Task:
//Calls:
//==================================================================
int hashClass::hash1(nameType name)
{
int sum = 0;
for(int i=0 ; i<strlen(name) ; i++)
sum = name[i] + sum;
return (sum % ARRAYSIZE);
}
//##################################################################
//Function:
//Task:
//Calls:
//==================================================================
int hashClass::hash2(int key){ return(STEPSIZE - (key % STEPSIZE)) }
//##################################################################
//Function:
//Task:
//Calls:
//==================================================================
int hashClass::checkOccupied()
{
int occupied = 0;
for(int i=0 ; i<ARRAYSIZE ; i++)
if(hashPtr[i].exist == TRUE)
occupied++;
return occupied;
}
//##################################################################
//Function:
//Task:
//Calls:
//==================================================================
void hashClass::destroyHash(int oldSize)
{
for(int i = 0; i < oldSize; i++)
delHash(i);
}
//##################################################################
//Function:
//Task:
//Calls:
//==================================================================
void hashClass::del(int location)
{
strcpy(hashPtr[location].name, "");
strcpy(hashPtr[location].number, "");
hashPtr[location].exist = TRUE;
}
//##################################################################
//Function:
//Task:
//Calls:
//==================================================================
void hashClass::delHash(int location)
{
strcpy(hashPtr[location].name, "");
strcpy(hashPtr[location].number, "");
hashPtr[location].exist = FALSE;
}
//##################################################################
//Function:
//Task:
//Calls:
//==================================================================
void hashClass::insert(int location, hashNode &newNode)
{
strcpy(hashPtr[location].name, newNode.name);
strcpy(hashPtr[location].number, newNode.number);
hashPtr[location].exist = TRUE;
}
//##################################################################
//Function:
//Task:
//Calls:
//==================================================================
void hashClass::save(fstream &fil)
{
int i = 0;
while(i < ARRAYSIZE) {
if((hashPtr[i].name[0]) && (hashPtr[i].exist == TRUE))
fil.write((char*)& hashPtr[i],sizeof(hashPtr[i]));
i++;
}
}

83
Hashing/header.hpp Normal file
View File

@@ -0,0 +1,83 @@
//##################################################################
// PROGRAMMERINGSUPPGIFT 3
// DATASTRUKTURER OCH ALGORITMER
// HASH TABELL
//==================================================================
// HEADER.HPP
// Filen innehåller definition som används i programmet
// Christian Ohlsson
// Ingela Johansson
// Anna-Maria Haglund
// Karlstad 981007
//==================================================================
#ifndef _header_
#define _header_
#include <iostream.h> //för in och utmatning
#include <fstream.h> //för filhantering
#include <iomanip.h> //för textmanipulation
#include <string.h> //för strängmanipulation
#include <conio.h> //för getch()
#include <ctype.h> //för isalnum
#include <stdlib.h> //för en massa saker
const int FALSE = 0; //boolsk variabel
const int TRUE = !FALSE //boolsk variabel
const int FILENAMESIZE = 8; //för MS-DOS 6.0
const int NAMESIZE = 20; //antal tecken som kan matas in som namn
const int NUMBERSIZE = 20; //antal tecken som kan matas in som nummer
const int ENTER = 13; //ASCII kod för enter
const int BACKSPACE = 8; //ASCII kod för backspace
const int PRIMEARRAYSIZE = 30; //storlek på primtalsarrayen
const int DEFAULTSIZE = 11; //hasharrayens defaultstorlek
const int TABSIZE = 20; //antal steg som motsvarar TAB
const int STEPSIZE = 7; //antal steg hash2 max stegar fram
const int DEFAULTPRIMENUMBER = 4; //minsta primtalet i arrayen
const int FIRSTPRIME = 3; //första talet som man jämför med
const int STARTPRIME = 2; //första primtalet i arrayen
const int PRIMESTEP = 2; //antal steg som man hoppar fram
const float INSERTFACTOR = 0.8; //ger en omhashning när 80% är upptaget
const float DELETEFACTOR = 0.3; //ger en omhashning när 30% är märkta deleted
typedef int bool; //definierar boolesk variabel
typedef char nameType[NAMESIZE]; //sätter nametypen till char
typedef char numberType[NUMBERSIZE]; //sätter numberTypen till char
struct hashNode{ //en nod
nameType name;
numberType number;
bool exist;
};
class hashClass
{
public:
hashClass();
~hashClass();
bool search(nameType name);
hashNode getNode(nameType &oneName);
int hash1(nameType name);
int hash2(int key);
int getSize();
void newHashArray();
void reHash(int oldSize);
void print();
void prime();
int checkOccupied();
void destroyHash(int oldSize);
bool biggerHash();
bool anotherHash();
void del(int location);
void insert(int location, hashNode &newNode);
void save(fstream &fil);
hashNode *hashPtr;
int nextPrime();
private:
void delHash(int location);
bool isPrime(int nummer, int antal, int primeArray[PRIMEARRAYSIZE]);
int ARRAYSIZE;
int primeArray[];
int PRIMENUMBER;
};
#endif

294
Hashing/huvud.cpp Normal file
View File

@@ -0,0 +1,294 @@
//##################################################################
// PROGRAMMERINGSUPPGIFT 3
// DATASTRUKTURER OCH ALGORITMER
// HASH TABELL
//==================================================================
// HUVUD.CPP
// Filen innehåller huvudprogrammet
// Christian Ohlsson
// Ingela Johansson
// Anna-Maria Haglund
// Karlstad 981007
//==================================================================
#include "header.hpp"
//###############################################################
// SÄKER INMATNING AV MENYVAL
// ser till att bara en character matas in
// som menyval som dessutom måste vara en siffra
//===============================================================
char mataInChar()
{
bool test = FALSE;
char temp, svar;
do {
temp = getch();
if(isalnum(temp) && test == FALSE) {
cout << temp;
svar = temp;
test = TRUE;
}
else if(temp == BACKSPACE && test == TRUE) {
gotoxy(wherex()-1, wherey());
cout << " ";
gotoxy(wherex()-1, wherey());
test = FALSE;
}
}while(temp != ENTER || test == FALSE);
return svar;
}
//##################################################################
//Function:
//Task:
//Calls:
//==================================================================
void _insert(hashClass &hashTable)
{
nameType name;
numberType number;
hashNode newNode;
int location;
if(hashTable.biggerHash() == FALSE) {
cout << "\n Skriv in namn: ";
cin >> name;
if(hashTable.search(name) == FALSE) {
cout << "\n Skriv in nummer: ";
cin >> number;
strcpy(newNode.name, name);
strcpy(newNode.number, number);
location = hashTable.hash1(name);
if(hashTable.hashPtr[location].exist == FALSE)
hashTable.insert(location, newNode);
else
while(hashTable.hashPtr[location].exist == TRUE) {
location = location + hashTable.hash2(hashTable.hash1(newNode.name));
if(location > hashTable.getSize())
location = location - hashTable.getSize();
if(hashTable.hashPtr[location].exist == FALSE) {
hashTable.insert(location, newNode);
return;
}
}
}
else {
cout << "\n Du har redan satt in " << name << " i katalogen";
getch();
}
}
else
hashTable.newHashArray();
}
//##################################################################
//Function:
//Task:
//Calls:
// TAR BORT EN NOD UR TRÄD
// calls: hashClass::del, getSize, search, hash1, hash2
//==================================================================
void _del(hashClass &hashTable)
{
nameType name;
int location;
cout << "\n Vem vill du ta bort: ";
cin >> name;
if(hashTable.search(name)) {
if(hashTable.anotherHash() == FALSE) {
location = hashTable.hash1(name);
if(strcmp(hashTable.hashPtr[location].name, name) == 0)
hashTable.del(location);
else {
while(hashTable.hashPtr[location].exist == TRUE) {
location = location + hashTable.hash2(hashTable.hash1(name));
if(location > hashTable.getSize())
location = location - hashTable.getSize();
if(strcmp(hashTable.hashPtr[location].name, name) == 0)
hashTable.del(location);
}
}
}
else
hashTable.reHash(hashTable.getSize());
}
else {
cout << " " << name << " finns inte i telefonkatalogen";
getch();
}
}
//##################################################################
//Function:
//Task:
//Calls:
// SKRIVER UT I INORDER
// calls: hashClass::print
//==================================================================
void _print(hashClass &hashTable)
{
int size = hashTable.getSize();
clrscr();
cout << "Plats"
<< setw(TABSIZE-3)
<< "Namn"
<< setw(TABSIZE)
<< "Nummer"
<< "\n-------------------------------------------";
for(int i=0 ; i < size ; i++)
if(hashTable.hashPtr[i].exist == TRUE && hashTable.hashPtr[i].name[0])
cout << endl
<< i
<< setw(TABSIZE)
<< hashTable.hashPtr[i].name
<< setw(TABSIZE)
<< hashTable.hashPtr[i].number;
cout << "\n\n\n\n Arrayen är nu " << size << " stor"
<< "\n och " << hashTable.checkOccupied() << " platser är upptagna.";
getch();
}
//##################################################################
//Function:
//Task:
//Calls:
// SÖKER I TRÄDET
// calls: hashClass::search
// calls: hashClass::isEmpty
//==================================================================
void _search(hashClass &hashTable)
{
hashNode newNode;
nameType name;
cout << "\n Mata in namn: ";
cin >> name;
if(hashTable.search(name)) {
newNode = hashTable.getNode(name);
cout << "\n "
<< newNode.name
<< " har telefonnummer "
<< newNode.number
<< ".";
}
else
cout << " " << name << " finns inte i telefonkatalogen";
getch();
}
//##################################################################
//Function:
//Task:
//Calls:
// SPARAR TRÄDET PÅ FIL
// calls: hashClass::save
// calls: hashClass::isEmpty
//==================================================================
void _save(hashClass &hashTable)
{
fstream fil;
char filnamn[FILENAMESIZE];
cout << "\n Ange filnamn att spara: ";
cin >> filnamn;
fil.open(filnamn,ios::out|ios::binary);
hashTable.save(fil);
fil.close();
}
//##################################################################
//Function:
//Task:
//Calls:
// HÄMTAR ETT TRÄD FRÅN EN FIL
// läser in värdet i varje nod i preorder
// och sätter in det i trädet i preoder
// calls hashClass::insert
// calls: hashClass::isEmpty
//==================================================================
void _load(hashClass &hashTable)
{
fstream fil;
int i = 0;
char filnamn[FILENAMESIZE];
cout << "\n Ange filnamn att hämta: ";
cin >> filnamn;
hashTable.destroyHash(hashTable.getSize());
fil.open(filnamn,ios::in|ios::binary);
if(fil) {
while(fil.peek() != EOF) {
fil.read((char*)& hashTable.hashPtr[i],sizeof(hashTable.hashPtr[i]));
hashTable.insert(i, hashTable.hashPtr[i]);
i++;
}
}
else {
cerr << "\n Filen finns inte...";
getch();
}
hashTable.reHash(hashTable.getSize());
fil.close();
}
//##################################################################
//Function:
//Task:
//Calls:
// DESTROYTREE
// tar bort hela trädet
// calls: hashClass::isEmpty
// calls: hashClass::destroyHash
//==================================================================
void _destroyHash(hashClass &hashTable)
{
hashTable.destroyHash(hashTable.getSize());
cerr << "\n Telefonkatalogen är tom...";
getch();
}
//##################################################################
//Function:
//Task:
//Calls:
// MENY ITEMS
// skriver ut menyn på skärmen
//==================================================================
void meny()
{
clrscr();
cout << " \n TELEFON KATALOGEN "
<< " \n ----------------- "
<< " \n 1. Lägg till person "
<< " \n 2. Ta bort person "
<< " \n 3. Sök efter person "
<< " \n 4. Skriv ut "
<< " \n 5. Spara på fil "
<< " \n 6. Hämta från fil "
<< " \n 7. Radera hela katalogen "
<< " \n 0. Avsluta ";
gotoxy(2,12); //ställer markören under menyn
}
//##################################################################
//Function:
//Task:
//Calls:
// MAIN FUNCTION
// skapar trädet hashTable av typen hashClass
// calls: alla drivrutiner
//==================================================================
void main()
{
hashClass hashTable;
char val;
do {
meny();
val = mataInChar();
switch (val)
{
case '1' : _insert(hashTable);break;
case '2' : _del(hashTable);break;
case '3' : _search(hashTable);break;
case '4' : _print(hashTable);break;
case '5' : _save(hashTable);break;
case '6' : _load(hashTable);break;
case '7' : _destroyHash(hashTable);break;
case '0' : cout << "\n Programmet avslutat";break;
default : cerr << "\n Felaktigt val";getch();
}
}while(val != '0');
exit(0);
}