Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
H
hashtable-open-addressing
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
David Nieder
hashtable-open-addressing
Commits
5a554820
Commit
5a554820
authored
2 years ago
by
David Nieder
Browse files
Options
Downloads
Patches
Plain Diff
a first draft
parent
a29a20dc
No related branches found
No related tags found
No related merge requests found
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
src/hashtable.cpp
+156
-0
156 additions, 0 deletions
src/hashtable.cpp
src/hashtable.h
+41
-0
41 additions, 0 deletions
src/hashtable.h
with
197 additions
and
0 deletions
src/hashtable.cpp
+
156
−
0
View file @
5a554820
#include
<cmath>
#include
<cassert>
#include
<iostream>
#include
<stdexcept>
#include
"hashtable.h"
Hashtable
::
Hashtable
(
size_t
m
,
float
alpha
,
float
s
)
:
slot_count
(
m
),
max_loadfactor
(
alpha
),
growfactor
(
s
),
table
(
new
Slot
[
m
])
{
if
(
!
(
0
<
alpha
&&
alpha
<
1
))
throw
std
::
invalid_argument
(
"load factor alpha must be in range (0;1)"
);
if
(
!
(
s
>
1
))
throw
std
::
invalid_argument
(
"grow factor s must be greater 1"
);
}
float
Hashtable
::
load_factor
()
const
{
return
slot_count
==
0
?
0
:
static_cast
<
float
>
(
element_count
)
/
slot_count
;
}
bool
Hashtable
::
insert
(
unsigned
key
)
{
// Grow the table if inserting would exceed the load factor.
// If the key is already in the table this could grow the table unnecessarily once.
if
(
slot_count
==
0
||
(
element_count
+
1.0f
)
/
slot_count
>
max_loadfactor
)
grow
();
unsigned
hk
=
hash
(
key
);
for
(
size_t
i
=
0
;
i
<
slot_count
;
i
++
)
{
Slot
&
slot
=
table
[
probe
(
hk
,
i
)];
if
(
slot
.
label
==
Slot
::
used
&&
slot
.
key
==
key
)
{
// the key is already in the table
return
false
;
}
if
(
slot
.
label
==
Slot
::
vacant
||
slot
.
label
==
Slot
::
deleted
)
{
// found an empty slot
element_count
++
;
slot
.
key
=
key
;
slot
.
label
=
Slot
::
used
;
return
true
;
}
}
// If the probing strategy permutates {0,...,m-1} the for-loop
// visits every slot and will find an empty one eventually.
throw
std
::
logic_error
(
"will we ever reach here?"
);
}
bool
Hashtable
::
remove
(
unsigned
key
)
{
if
(
slot_count
==
0
)
return
false
;
// table is empty
unsigned
hk
=
hash
(
key
);
for
(
size_t
i
=
0
;
i
<
slot_count
;
i
++
)
{
Slot
&
slot
=
table
[
probe
(
hk
,
i
)];
if
(
slot
.
label
==
Slot
::
vacant
)
{
// found a vacant slot: key is not in table
break
;
}
if
(
slot
.
label
==
Slot
::
used
&&
slot
.
key
==
key
)
{
// found the key: mark slot deleted
element_count
--
;
slot
.
label
=
Slot
::
deleted
;
return
true
;
}
}
return
false
;
}
bool
Hashtable
::
contains
(
unsigned
key
)
{
if
(
slot_count
==
0
)
return
false
;
// table is empty
unsigned
hk
=
hash
(
key
);
for
(
size_t
i
=
0
;
i
<
slot_count
;
i
++
)
{
Slot
&
slot
=
table
[
probe
(
hk
,
i
)];
if
(
slot
.
label
==
Slot
::
vacant
)
{
// found a vacant slot, key is not in table
break
;
}
if
(
slot
.
label
==
Slot
::
used
&&
slot
.
key
==
key
)
{
return
true
;
}
}
return
false
;
}
inline
unsigned
Hashtable
::
hash
(
unsigned
key
)
{
assert
(
slot_count
!=
0
);
return
key
%
slot_count
;
}
inline
size_t
Hashtable
::
probe
(
unsigned
h
,
size_t
i
)
{
assert
(
slot_count
!=
0
);
return
(
h
+
i
)
%
slot_count
;
}
void
Hashtable
::
grow
()
{
size_t
old_capacity
=
slot_count
;
slot_count
=
std
::
ceil
(
growfactor
*
(
slot_count
==
0
?
1
:
slot_count
));
Slot
*
const
new_table
=
new
Slot
[
slot_count
];
// for all slots in the old table ...
for
(
size_t
i
=
0
;
i
<
old_capacity
;
i
++
)
{
Slot
&
os
=
table
[
i
];
// that store a key ...
if
(
os
.
label
==
Slot
::
used
)
{
unsigned
hk
=
hash
(
os
.
key
);
// find a slot in the new table
for
(
size_t
j
=
0
;
j
<
slot_count
;
j
++
)
{
Slot
&
ns
=
new_table
[
probe
(
hk
,
j
)];
if
(
ns
.
label
==
Slot
::
vacant
)
{
ns
.
key
=
os
.
key
;
ns
.
label
=
Slot
::
used
;
break
;
}
}
}
}
table
.
reset
(
new_table
);
// smart_ptr frees the old table
}
void
Hashtable
::
info
()
const
{
std
::
cerr
<<
"size: "
<<
size
()
<<
", capacity: "
<<
capacity
()
<<
", alpha (current/max): "
<<
load_factor
()
<<
"/"
<<
max_loadfactor
<<
std
::
endl
;
std
::
cerr
<<
"array size: "
<<
slot_count
*
sizeof
(
Slot
)
/
1024
<<
"kB, start: "
<<
table
.
get
()
<<
", end: "
<<
table
.
get
()
+
slot_count
<<
std
::
endl
;
}
void
Hashtable
::
print
()
const
{
for
(
size_t
i
=
0
;
i
<
slot_count
;
i
+=
10
)
{
std
::
cerr
<<
i
<<
": "
;
for
(
size_t
j
=
i
;
j
<
i
+
10
&&
j
<
slot_count
;
j
++
)
{
Slot
s
=
table
[
j
];
std
::
string
repr
;
if
(
s
.
label
==
Slot
::
vacant
)
repr
=
"F"
;
else
if
(
s
.
label
==
Slot
::
deleted
)
repr
=
"D"
;
else
repr
=
std
::
to_string
(
s
.
key
);
std
::
cerr
<<
repr
<<
" "
;
}
std
::
cerr
<<
std
::
endl
;
}
}
This diff is collapsed.
Click to expand it.
src/hashtable.h
+
41
−
0
View file @
5a554820
#ifndef HASHTABLE_H
#define HASHTABLE_H
#include
<memory>
/* a bucket of size 1 */
class
Slot
{
unsigned
key
=
0
;
enum:
char
{
vacant
,
deleted
,
used
}
label
=
vacant
;
friend
class
Hashtable
;
};
class
Hashtable
{
public:
Hashtable
(
size_t
m
=
8
,
float
alpha
=
0.75
,
float
s
=
2.0
);
bool
insert
(
unsigned
key
);
bool
remove
(
unsigned
key
);
bool
contains
(
unsigned
key
);
size_t
size
()
const
{
return
element_count
;
}
size_t
capacity
()
const
{
return
slot_count
;
}
float
load_factor
()
const
;
void
info
()
const
;
void
print
()
const
;
private
:
size_t
element_count
=
0
;
size_t
slot_count
;
const
float
max_loadfactor
;
const
float
growfactor
;
std
::
unique_ptr
<
Slot
[]
>
table
;
unsigned
hash
(
unsigned
key
);
size_t
probe
(
unsigned
key
,
size_t
i
);
void
grow
();
};
#endif
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment