|
2 | 2 | from pydatastructs.utils.misc_util import _check_type, NoneType
|
3 | 3 |
|
4 | 4 | __all__ = [
|
5 |
| -'OneDimensionalArray' |
| 5 | +'OneDimensionalArray', |
| 6 | +'DynamicOneDimensionalArray' |
6 | 7 | ]
|
7 | 8 |
|
8 | 9 | class Array(object):
|
@@ -112,3 +113,129 @@ def fill(self, elem):
|
112 | 113 | elem = self._dtype(elem)
|
113 | 114 | for i in range(self._size):
|
114 | 115 | 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 |
0 commit comments