一、【資料結構】向量(vector)的實現
本文使用c++實現vector資料結構,vector的介面函式採用高效的實現方式,這樣一方面使我加深對資料結構的理解,另一方便可以讓我再回顧回顧c++,之前寫了好久python都快把c++忘記了。
操作 | 功能 | 物件 |
vector(int c, Rank s, T v) | 設定容量、初始大小、元素初始值 | |
vector(int c, Rank s) | 設定容量、初始大小 | |
vector(initializer_list<T>) | 列表初始化方式構造 | |
vector(const vector<T>& A, Rank lo, Rank hi) | 從另一vector拷貝構造新vector物件 | |
~vector() | 解構函式,手動釋放動態陣列所佔的空間 | |
expand() | 容量更新(擴容) | 向量 |
sharink() | 容量更新(縮減) | 向量 |
display() | 列印vector內部元素 | 向量 |
size() | 返回vector當前有效尺寸 | 向量 |
get(Rank r) | 獲取指定元素 | 向量 |
put(Rank r, const T e) | 替換指定元素 | 向量 |
permute() | 打亂vector順序 | 向量 |
unsort(Rank lo, Rank hi) | 打亂vector指定區間的順序 | 向量 |
find(Rank lo,Rank hi,const T e) | 在指定區間查詢指定元素 | 向量 |
insert(Rank r, const T& e) | 在指定區間插入元素 | 向量 |
insert(const T& e) | 在尾部插入元素 | 向量 |
remove(Rank lo, Rank hi) | 刪除指定區間的元素 | 向量 |
remove(Rank r) | 刪除單個元素 | 向量 |
deduplicate() | 除去重複元素 | 向量 |
traverse(void(*func)(T& a)) | 用指定函式批量處理元素(函式指標方式) | 向量 |
traverse(FunClass func) | 用指定函式批量處理元素(函式物件方式) | 向量 |
disordered() | 判斷是不是有序向量 | 向量 |
uniquify() | 除去重複元素 | 有序向量 |
search(Rank lo, Rank hi, const T e) | 在指定區間中查詢元素 | 有序向量 |
binsearch(Rank lo, Rank hi, const T e) | 在指定區間中查詢元素(二分查詢) | 有序向量 |
sort(Rank lo, Rank hi, int a) | 排序演算法彙總 | 向量 |
bubbleSort(Rank lo, Rank hi) | 氣泡排序 | 向量 |
mergeSort(Rank lo, Rank hi) | 歸併排序 | 向量 |
過載運算子[] | 下標運算子 | 向量 |
過載運算子= | 賦值運算子 | 向量 |
過載運算子= | 賦值運算子(列表賦值方式) | 向量 |
過載運算子== | 相等判斷運算子 | 向量 |
過載運算子<= | 小於等於判斷運算子 | 向量 |
過載運算子>= | 大於等於判斷運算子 | 向量 |
#pragma once
#define DEFAULT_CAPACITY 10 //預設容量大小
using namespace std;
typedef int Rank;
template <typename T>
class vector
{
protected:
Rank _size;
int _capacity;
T *_elem; //vector內部所維護的陣列的指標
public:
//建構函式(容量,初始大小,初始值)
vector(int c = DEFAULT_CAPACITY, Rank s = 0, T v = 0);
vector(initializer_list<T>); //列表初始化方式
vector(const vector<T>& A, Rank lo, Rank hi);
//解構函式
~vector();
//複製建構函式
void copyFrom(const vector<T>& A, Rank lo, Rank hi);
//容量更新(擴容和縮減)
void expand();
void sharink();
//普通成員函式
void display() const; //列印vector內部元素
Rank size() const; //返回vector當前size
T get(Rank r); //獲取指定元素
void put(Rank r, const T e); //替換指定元素
void permute(); //打亂順序
void unsort(Rank lo, Rank hi); //打亂區間順序
Rank find(Rank lo,Rank hi,const T e); //查詢指定元素
Rank insert(Rank r, const T& e); // 插入
Rank insert(const T& e); //在向量尾部插入
int remove(Rank lo, Rank hi); //刪除指定區間的元素
T remove(Rank r); //刪除指定索引的單個元素
void deduplicate(); //除去重複元素
void traverse(void(*func)(T& a)); //用指定函式批量處理元素(函式指標方式)
template<typename FunClass> void traverse(FunClass func); //用指定函式批量處理元素(函式物件方式)
bool disordered() const; //判斷是不是有序向量
void uniquify(); //有序向量除去重複元素
Rank search(Rank lo, Rank hi, const T e); //有序向量,在指定區間中查詢元素
Rank search(const T e);
Rank binsearch(Rank lo, Rank hi, const T e); //有序向量,二分查詢
void swap(T& a, T& b); //交換元素值
void sort(Rank lo, Rank hi, int a); //排序演算法彙總
void bubbleSort(Rank lo, Rank hi); //氣泡排序
void mergeSort(Rank lo, Rank hi); //歸併排序(遞迴實現)
//過載運算子
T& operator[](const Rank i) const; //下標運算子
vector<T>& operator=(const vector<T> &A); //賦值運算子
vector<T>& operator=(initializer_list<T>); //賦值運算子,列表初始化
bool operator==(const vector<T>& A); //判等運算子
bool operator<=(const vector<T>& A); //小於等於判斷
bool operator>=(const vector<T>& A); //大於等於判斷
};
//實現c++中vector容器底層(具體實現也要放在與宣告同樣的檔案中)
template <typename T> vector<T>::vector(int c, Rank s, T v)
{
_elem = new T[_capacity = c]; //申請容量為T*c的記憶體空間並用_elem指標指向該地址
for (_size = 0; _size < s; _elem[_size++] = v); //對有效值進行初始化並更新_size
}
template<typename T> vector<T>::vector(initializer_list<T> li)
{
_elem = new T[_capacity = li.size()];
for (auto iter = li.begin(); iter != li.end(); iter++)
_elem[_size++] = *iter;
}
template <typename T> vector<T>::vector(const vector<T>& A, Rank lo, Rank hi)
{
copyFrom(A, lo, hi);
}
template <typename T> vector<T>::~vector()
{
//釋放陣列中的空間
delete[] _elem;
}
template <typename T> void vector<T>::copyFrom(const vector<T>& A, Rank lo, Rank hi)
{
_capacity = (hi - lo) << 1;
_size = 0;
_elem = new T[_capacity]; //申請記憶體
while (lo < hi)
{
_elem[_size++] = A[lo++];
}
}
template<typename T> void vector<T>::display() const
{
if (_size)
{
for (int i = 0; i < _size - 1; i++)
{
cout << _elem[i] << ",";
}
cout << _elem[_size - 1] << endl;
}
}
//過載[]運算子
template<typename T> T& vector<T>::operator[](const Rank i) const
{
return _elem[i];
}
template<typename T> vector<T>& vector<T>::operator=(const vector<T> &A)
{
//釋放之前的空間,後面會自動建立
delete[] _elem;
copyFrom(A, 0, A.size());
return *this; //返回this的引用才能連續賦值A=B=C
}
template<typename T> vector<T>& vector<T>::operator=(initializer_list<T> li)
{
delete[] _elem;
_size = 0;
_capacity = li.size() << 1;
_elem = new T[_capacity]; //申請記憶體
for(auto iter=li.begin();iter!=li.end(); iter++)
_elem[_size++] = *iter;
return *this;
}
template<typename T> Rank vector<T>::size() const
{
return _size;
}
template<typename T> T vector<T>::get(Rank r)
{
return _elem[r];
}
template<typename T> void vector<T>::put(Rank r, const T e)
{
_elem[r] = e;
}
template<typename T> void vector<T>::expand()
{
if (_size < _capacity) return;
if (_capacity < DEFAULT_CAPACITY) _capacity = DEFAULT_CAPACITY;
T* oldElem = _elem; _elem = new T[_capacity <<= 1];
for (int i = 0; i < _size; i++)
_elem[i] = oldElem[i];
delete[] oldElem;
}
//{
// //cout << "enpand():the old capacity: " << _capacity << endl;
// if (_capacity < DEFAULT_CAPACITY) _capacity = DEFAULT_CAPACITY;
// if ((_capacity >> 1) < _size) { //如果_capacity不大於_size的兩倍,擴容
// T* tempPtr = new T[_capacity=(_size << 1)];
// //cout << "_size" << _size << endl;
// for(int i=0;i<_size;i++)
// {
// tempPtr[i] = _elem[i]; //轉移資料
// //cout << "i:" << i << endl;
// }
// delete[] _elem; //清除之前的空間
// _elem = tempPtr; //指標指向新的空間
// }
// //cout << "enpand():the new capacity: " << _capacity << endl;
//}
template<typename T> void vector<T>::sharink()
{
//cout << "sharink():the old capacity: " << _capacity << endl;
if (_size < _capacity/4.0) //_size小於_capacity的1/4,縮減
{
T *tempPtr = ((_size << 1) > DEFAULT_CAPACITY) ? new T[_capacity =(_size<<1)] : new T[_capacity = DEFAULT_CAPACITY];
for (int i = 0; i < _size; i++)
{
tempPtr[i] = _elem[i];
//cout << "i:" << i << endl;
}
delete[] _elem;
_elem = tempPtr; //更新指標指向
}
//cout << "sharink():the new capacity: " << _capacity << endl;
}
template<typename T> void vector<T>::permute()
{
for(int i=0;i<_size;i++)
{
swap(_elem[i], _elem[rand()%_size]); //隨機找一個替換
}
}
template<typename T> void vector<T>::unsort(Rank lo,Rank hi)
{
for (int i = lo; i < hi; i++)
{
swap(_elem[i], _elem[rand() % (hi - lo) + lo]);
}
}
template<typename T> bool vector<T>::operator==(const vector<T>& A)
{
if (_size != A.size()) return false;
for (int i = 0; i < _size; i++)
{
if(_elem[i] != A[i]) return false;
}
return true;
}
template<typename T> bool vector<T>::operator<=(const vector<T>& A)
{
int min = (_size <= A.size()) ? _size : A.size();
for (int i = 0; i < min; i++)
{
if ((*this)[i] != A[i])
return ((*this)[i] <= A[i]) ? true : false;
}
return (_size <= A.size()) ? true : false;
}
template<typename T> bool vector<T>::operator>=(const vector<T>& A)
{
int min = (_size <= A.size()) ? _size : A.size();
for (int i = 0; i < min; i++)
{
if ((*this)[i] != A[i])
return ((*this)[i] >= A[i]) ? true : false;
}
return (_size >= A.size()) ? true : false;
}
template<typename T> Rank vector<T>::find(Rank lo, Rank hi, const T e) // 前閉後開
{
while ((hi--)>lo)
{
if(_elem[hi] == e) break;
}
return hi;
}
template<typename T> Rank vector<T>::insert(Rank r, const T& e)
{
expand();
//Rank從r至以後的元素都要往後面移一位
for (int i = _size; i > r; i--)
{
_elem[i] = _elem[i - 1];
}
_elem[r] = e;
_size++;
return r;
}
template<typename T> Rank vector<T>::insert(const T& e)
{
return insert(_size, e);
}
template<typename T> int vector<T>::remove(Rank lo, Rank hi) //前閉後開
{
//首先指定後界秩後面的元素都往前面移動(hi-lo+1)個位置,原位置置零
if (lo == hi) return 0;
while(hi<_size)
{
_elem[lo++] = _elem[hi];
_elem[hi++] = 0;
}
//更新_size
_size -= (hi - lo);
sharink();
return (hi - lo);
}
template<typename T> T vector<T>::remove(Rank r)
{
T e = _elem[r];
remove(r, r + 1);
return e;
}
template<typename T> void vector<T>::deduplicate()
{
if (!_size) return;
Rank rl = 0; //第rl個是已經確認無重的最後一個
Rank rr = 1; //第rr個是要判斷的
while (rr < _size) // _size會減,rr會加
{
if (find(0, rl + 1, _elem[rr]) >= 0) //確認是之前出現過
remove(rr);
else
{
rl++; //加入一個有效值
rr++;
}
}
}
template<typename T> void vector<T>::traverse(void(*func)(T& a))
{
for (int i = 0; i < _size; i++)
{
func(_elem[i]);
}
}
template<typename T> template<typename FunClass> void vector<T>::traverse(FunClass func)
{
for (int i = 0; i < _size; i++)
{
func(_elem[i]);
}
}
template<typename T> bool vector<T>::disordered() const
{
for (int i = 0; i < _size - 1; i++)
{
if (_elem[i] > _elem[i + 1])
{
return false;
}
}
return true;
}
template<typename T> void vector<T>::uniquify()
{
if (_size<=1) return;
Rank rl=0; //已經確認好的序列的最後一個元素的秩
Rank rr=1; //正要判斷的元素的秩
while (rr < _size)
{
if (_elem[rr] != _elem[rr - 1]) //發現一個新值,移動到rl+1
{
_elem[++rl] = _elem[rr++];
}
else
rr++;
}
_size = rl + 1;
sharink();
}
template<typename T> Rank vector<T>::search(Rank lo, Rank hi, const T e)
{
return binsearch(lo, hi, e);
}
template<typename T> Rank vector<T>::search(const T e)
{
return (_size <= 0) ? -1 : search(0, _size, e);
}
template<typename T> Rank vector<T>::binsearch(Rank lo, Rank hi, const T e) // [0][1][2][m][4][5][6][7][-hi-]
{
//方法一
//把mi這一點作為一個分界線,單數直接作為右側區間的左端點
Rank mi;
while (lo < hi)
{
mi = (lo + hi) >> 1; //取中點的時候是往左偏的
(e < _elem[mi]) ? hi = mi : lo = mi+1; //都是左閉右開區間
}
return --lo;
}
//{ //方法二
// Rank mi;
// while (lo<hi)
// {
// mi = (lo + hi) >> 1;
// if (_elem[mi] < e)
// lo = mi + 1;
// else if(_elem[mi] > e)
// hi = mi; //都是左閉右開區間
// else
// return mi;
// }
// return -1;
//}
template<typename T> void vector<T>::swap(T& a, T& b)
{
a = a^b; //原理:(a^b)^a=b
b = a^b;
a = a^b;
}
template<typename T> void vector<T>::sort(Rank lo, Rank hi, int a)
{
switch (a)
{
case 1:
bubbleSort(lo, hi); break; //氣泡排序
case 2:;
//selectSort(lo, hi); break; //選擇排序
case 3:
mergeSort(lo, hi); break; //歸併排序
case 4:;
//heapSort(lo, hi); break; //堆排序
default:;
//quickSort(lo, hi); break; //快速排序
}
}
template<typename T> void vector<T>::bubbleSort(Rank lo, Rank hi)
{
bool sorted = false; //已有序標誌
while (!sorted) //如果有序,提前退出
{
sorted = true;
for (int i = lo; i < hi - 1; i++) //在一次迴圈中如果發現逆序,就置標誌位為false
{
if (_elem[i] > _elem[i + 1])
{
sorted = false;
swap(_elem[i], _elem[i + 1]);
}
}
hi--;
}
}
template<typename T> void vector<T>::mergeSort(Rank lo, Rank hi) //左閉右開區間
{
if (!(lo < hi-1)) //只有一個元素則不用排序
return;
Rank mi = (lo + hi) >> 1; //[0][1][2] [3]
mergeSort(lo, mi);
mergeSort(mi, hi);
//開始歸併
T* A = _elem + lo;
T* C = _elem + mi;
int lb = mi - lo; //1
int lc = hi - mi; //2
T* B = new T[lb];
for (int i = 0; i < lb; i++)
B[i] = A[i]; //複製元素到新空間
//比較B和C所指序列的大小,將結果放置在A處
for (int a=0, i = 0, j = 0; i < lb || j < lc;)
{
if (i < lb&&j < lc) //兩個序列都還有剩餘
A[a++] = (B[i] < C[j]) ? B[i++] : C[j++];
if (i < lb && !(j < lc)) //只有B序列還有剩餘
A[a++] = B[i++];
if (!(i < lb) && j < lc) //只有C序列還有剩餘
A[a++] = C[j++];
}
delete[] B; //有new就要有delete
}
相關文章
- redis資料結構實現(一)Redis資料結構
- 資料結構--LinkedList的實現資料結構
- Java常用資料結構之Stack&VectorJava資料結構
- JavaScript資料結構——圖的實現JavaScript資料結構
- 資料庫-SQL_duckdb向量化計算-vector資料庫SQL
- js實現資料結構--棧JS資料結構
- 資料結構:稀疏棋盤的實現資料結構
- 資料結構(雙向連結串列的實現)資料結構
- Java實現資料結構之線性結構Java資料結構
- 一本正經的聊資料結構(2):陣列與向量資料結構陣列
- Redis資料結構(一)-Redis的資料儲存及String型別的實現Redis資料結構型別
- STL---vector(向量)
- python-Vector向量Python
- 資料結構——單連結串列的C++實現資料結構C++
- [資料結構]連結串列的實現在PHP中資料結構PHP
- [資料結構] 連結串列的實現在 PHP 中資料結構PHP
- Java關於資料結構的實現:樹Java資料結構
- 用go實現常見的資料結構Go資料結構
- js實現資料結構--陣列JS資料結構陣列
- js實現資料結構--佇列JS資料結構佇列
- 【資料結構】ArrayList原理及實現資料結構
- 資料結構之php實現棧資料結構PHP
- js實現資料結構--單連結串列JS資料結構
- 資料結構實驗 多維陣列的實現資料結構陣列
- 資料結構實驗 二維矩陣的實現資料結構矩陣
- 詳細分析連結串列的資料結構的實現過程(Java 實現)資料結構Java
- 資料結構-2.單向連結串列的實現資料結構
- 基礎資料結構(一)---(最全)定長順序表的實現資料結構
- Java關於資料結構的實現:雜湊Java資料結構
- JavaScript資料結構——集合的實現與應用JavaScript資料結構
- php實現基本資料結構之連結串列PHP資料結構
- 資料結構-雙向連結串列(Python實現)資料結構Python
- 資料結構 - 單連結串列 C++ 實現資料結構C++
- 資料結構 使用2個棧實現一個佇列資料結構佇列
- 資料結構和演算法(一)線性表實現資料結構演算法
- 資料結構 - 圖之程式碼實現資料結構
- Redis sds資料結構實現分析ZFRedis資料結構
- 資料結構之php實現佇列資料結構PHP佇列