数组基础
从概念上说,数组就是把数据码成一排进行存放。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 int main () { int arr[10 ]; for (int i = 0 ; i < 10 ; i++) { arr[i] = i; } int * arr2 = new int [10 ]; for (size_t index = 0 ; index < 10 ; index++) { arr2[index] = index; } delete [] arr2; int scores[] = { 100 ,99 ,98 }; for (auto score : scores) { cout << score << endl; } scores[1 ] = 66 ; for (size_t i = 0 ; i < sizeof (scores) / sizeof (scores[0 ]); i++) { cout << scores[i] << endl; } return 0 ; }
数组最重要的就是就是它的索引。索引可以有语义,也可以没有语义。数组最大的优点就是可以快速查询,直接用数组下标就可以找到元素,因此数组最好应用于“索引有语义”的情况,通俗的说就是我们最好知道我们要查什么。但也要注意并非所有有语义的索引都适用于数组,比如当我们要存储人员信息,索引是身份证号的话,需要为索引信息开辟大量的空间。
自己封装数组
使用原生的数组会有很多限制,比如数组开辟了连续的空间,但只有很少的空间存储了信息,如果索引没有语义,那么那些没有信息的空间如何表示呢?还有如何向数组添加元素,如何删除元素等等。所以我们需要编写自己的动态数组类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 template <typename T>class Array { public : Array (int capacity) { m_nCapacity = capacity; m_nSize = 0 ; m_arrData = new T[m_nCapacity]; } Array () { m_nSize = 0 ; m_nCapacity = 10 ; m_arrData = new T[10 ]; } ~Array () { if (m_arrData) { delete [] m_arrData; m_arrData = nullptr ; } m_nSize = 0 ; } public : int GetSize () { return m_nSize; } int GetCapacity () { return m_nCapacity; } bool IsEmpty () { return m_nSize == 0 ; } void Add (int index, T e) { assert (index >=0 && index <=m_nSize); if (m_nSize == m_nCapacity) Resize (2 * m_nCapacity); for (int i = m_nSize - 1 ; i >= index; i--) { m_arrData[i + 1 ] = m_arrData[i]; } m_arrData[index] = e; m_nSize++; } void AddLast (T e) { Add (m_nSize, e); } void AddFirst (T e) { Add (0 , e); } T Get (int index) { assert (index >= 0 && index < m_nSize); return m_arrData[index]; } void Set (int index, T e) { assert (index >= 0 && index < m_nSize); m_arrData[index] = e; } bool Contains (T e) { for (int i = 0 ; i < m_nSize; i++) { if (m_arrData[i] == e) return true ; } return false ; } int Find (T e) { for (int i = 0 ; i < m_nSize; i++) { if (m_arrData[i] == e) return i; } return -1 ; } T Remove (int index) { assert (index >= 0 && index < m_nSize); T ret = m_arrData[index]; for (int i = index + 1 ; i < m_nSize; i++) { m_arrData[i - 1 ] = m_arrData[i]; } m_nSize--; if (m_nSize == m_nCapacity / 2 ) Resize (m_nCapacity / 2 ); return ret; } int RemoveFirst () { return Remove (0 ); } int RemoveLast () { return Remove (m_nSize - 1 ); } void RemoveElement (T e) { int index = Find (e); if (index != -1 ) Remove (index); } void Print () { assert (m_nSize > 0 ); cout << "Array:size=" << m_nSize << ",capacity=" << m_nCapacity << endl; cout << "[" ; for (int i = 0 ; i < m_nSize; i++) { cout << m_arrData[i]; if (i != m_nSize - 1 ) cout << "," ; } cout << "]" << endl; } private : void Resize (int newCapacity) { T* newData = new T[newCapacity]; for (int i = 0 ; i < m_nSize; i++) { newData[i] = m_arrData[i]; } m_arrData = newData; m_nCapacity = newCapacity; newData = nullptr ; delete [] newData; } private : int m_nSize; int m_nCapacity; T* m_arrData; }; int main () { Array<int > *myArr = new Array <int >(3 ); myArr->AddLast (2 ); myArr->AddLast (3 ); myArr->AddFirst (1 ); myArr->Print (); myArr->AddFirst (10 ); myArr->Print (); myArr->RemoveFirst (); myArr->Print (); auto tmp1 = myArr->Get (1 ); bool b1 = myArr->Contains (6 ); myArr->Set (2 , 6 ); b1 = myArr->Contains (6 ); if (myArr) { delete myArr; myArr = nullptr ; } return 0 ; }
时间复杂度分析