Skip to content

Commit e820aa1

Browse files
authored
Added Dynamic Arrays (#28)
* added dynamic arrays * removed python2.7
1 parent 29e5744 commit e820aa1

File tree

4 files changed

+149
-3
lines changed

4 files changed

+149
-3
lines changed

.travis.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ sudo: false
33
language: python
44

55
python:
6-
- "2.7"
76
- "3.5"
87
install:
98
- pip install -r requirements.txt

pydatastructs/linear_data_structures/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@
66

77
from .arrays import (
88
OneDimensionalArray,
9+
DynamicOneDimensionalArray
910
)
1011
__all__.extend(arrays.__all__)

pydatastructs/linear_data_structures/arrays.py

Lines changed: 128 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
from pydatastructs.utils.misc_util import _check_type, NoneType
33

44
__all__ = [
5-
'OneDimensionalArray'
5+
'OneDimensionalArray',
6+
'DynamicOneDimensionalArray'
67
]
78

89
class Array(object):
@@ -112,3 +113,129 @@ def fill(self, elem):
112113
elem = self._dtype(elem)
113114
for i in range(self._size):
114115
self._data[i] = elem
116+
117+
ODA = OneDimensionalArray
118+
119+
class DynamicArray(Array):
120+
"""
121+
Abstract class for dynamic arrays.
122+
"""
123+
pass
124+
125+
class DynamicOneDimensionalArray(DynamicArray, OneDimensionalArray):
126+
"""
127+
Represents dynamic one dimensional arrays.
128+
129+
Parameters
130+
==========
131+
132+
dtype: type
133+
A valid object type.
134+
size: int
135+
The number of elements in the array.
136+
elements: list/tuple
137+
The elements in the array, all should
138+
be of same type.
139+
init: a python type
140+
The inital value with which the element has
141+
to be initialized. By default none, used only
142+
when the data is not given.
143+
load_factor: float, by default 0.25
144+
The number below which if the ratio, Num(T)/Size(T)
145+
falls then the array is contracted such that at
146+
most only half the positions are filled.
147+
148+
Raises
149+
======
150+
151+
ValueError
152+
When the number of elements in the list do not
153+
match with the size.
154+
More than three parameters are passed as arguments.
155+
Types of arguments is not as mentioned in the docstring.
156+
The load factor is not of floating point type.
157+
158+
Note
159+
====
160+
161+
At least one parameter should be passed as an argument along
162+
with the dtype.
163+
Num(T) means the number of positions which are not None in the
164+
array.
165+
Size(T) means the maximum number of elements that the array can hold.
166+
167+
Examples
168+
========
169+
170+
>>> from pydatastructs import DynamicOneDimensionalArray as DODA
171+
>>> arr = DODA(int, 0)
172+
>>> arr.append(1)
173+
>>> arr.append(2)
174+
>>> arr[0]
175+
1
176+
>>> arr.delete(0)
177+
>>> arr[0]
178+
>>> arr[1]
179+
2
180+
>>> arr.append(3)
181+
>>> arr.append(4)
182+
>>> [arr[i] for i in range(arr.size)]
183+
[None, 2, 3, 4, None, None, None]
184+
185+
References
186+
==========
187+
188+
.. [1] http://www.cs.nthu.edu.tw/~wkhon/algo09/lectures/lecture16.pdf
189+
"""
190+
191+
__slots__ = ['_load_factor', '_num', '_last_pos_filled', '_size']
192+
193+
def __new__(cls, dtype=NoneType, *args, **kwargs):
194+
obj = super().__new__(cls, dtype, *args, **kwargs)
195+
obj._load_factor = float(kwargs.get('load_factor', 0.25))
196+
obj._num = 0 if obj._size == 0 or obj[0] == None else obj._size
197+
obj._last_pos_filled = obj._num - 1
198+
return obj
199+
200+
def _modify(self):
201+
"""
202+
Contracts the array if Num(T)/Size(T) falls
203+
below load factor.
204+
"""
205+
if self._num/self._size < self._load_factor:
206+
arr_new = ODA(self._dtype, 2*self._num + 1)
207+
j = 0
208+
for i in range(self._last_pos_filled + 1):
209+
if self[i] != None:
210+
arr_new[j] = self[i]
211+
j += 1
212+
self._last_pos_filled = j - 1
213+
self._data = arr_new._data
214+
self._size = arr_new._size
215+
216+
def append(self, el):
217+
if self._last_pos_filled + 1 == self._size:
218+
arr_new = ODA(self._dtype, 2*self._size + 1)
219+
for i in range(self._last_pos_filled + 1):
220+
arr_new[i] = self[i]
221+
arr_new[self._last_pos_filled + 1] = el
222+
self._last_pos_filled += 1
223+
self._size = arr_new._size
224+
self._num += 1
225+
self._data = arr_new._data
226+
else:
227+
self[self._last_pos_filled + 1] = el
228+
self._last_pos_filled += 1
229+
self._num += 1
230+
self._modify()
231+
232+
def delete(self, idx):
233+
if idx <= self._last_pos_filled and idx >= 0 and \
234+
self[idx] != None:
235+
self[idx] = None
236+
self._num -= 1
237+
self._modify()
238+
239+
@property
240+
def size(self):
241+
return self._size

pydatastructs/linear_data_structures/tests/test_arrays.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from pydatastructs.linear_data_structures import OneDimensionalArray
1+
from pydatastructs.linear_data_structures import (
2+
OneDimensionalArray, DynamicOneDimensionalArray)
23
from pydatastructs.utils.raises_util import raises
34

45

@@ -17,3 +18,21 @@ def test_OneDimensionalArray():
1718
raises(TypeError, lambda: ODA(int, 5.0))
1819
raises(TypeError, lambda: ODA(int, set([1, 2, 3])))
1920
raises(ValueError, lambda: ODA(int, 3, [1]))
21+
22+
def test_DynamicOneDimensionalArray():
23+
DODA = DynamicOneDimensionalArray
24+
A = DODA(int, 0)
25+
A.append(1)
26+
A.append(2)
27+
A.append(3)
28+
A.append(4)
29+
A.delete(0)
30+
A.delete(0)
31+
A.delete(15)
32+
A.delete(-1)
33+
A.delete(1)
34+
A.delete(2)
35+
assert A._data == [4, None, None]
36+
assert A.size == 3
37+
A.fill(4)
38+
assert A._data == [4, 4, 4]

0 commit comments

Comments
 (0)