寫在前面
之前刷動態規劃的題目,多需要用到二維陣列(也許后面再優化成一維),如果每次都按照給定數的范圍直接宣告為全域二維陣列變數,又總覺得的不夠優雅,查閱了一些網上的資料后,總結了一些使用方法,就寫下這篇博文用以記錄,
方法1——動態分配(new)一維陣列,再強制型別轉換為二維(個人使用,推薦指數:????)
直接看例子
/** 假設需要根據兩個string的長度建立二維陣列 */
const int sz1 = str1.size();
const int sz2 = str2.size();
/** 動態分配記憶體 */
auto f = new int[sz1 * sz2];
auto dp = (int (*)[sz2])f;
/** 這里放置自己制造bug的操作*/
// abaabaaba, 直接dp[i][j]使用即可
/** 制造完了別忘記釋放堆疊空間 */
delete[] f;
f = nullptr;
dp = nullptr;
注意,auto dp = (int (*)[sz2]f這條陳述句,sz2的大小一定要是后面使用二維陣列時最低維的大小,
如果按照上面的型別轉換方式,下面這樣寫會出現bug(注意sz1和sz2的順序):
for (int i = 0; i < sz2; ++i)
for (int j = 0; j < sz1; ++j)
// do something;
/** 其實大概率你啥也do不了,程式跑飛了 */
這個方法優點和缺點都很明顯,靈活且完全和使用全域二維陣列方法一樣,且釋放記憶體簡單,但是使用存在危險性,如果覺得自己把握不住,建議先考慮其他方法,
另外,請讀者考慮一下,可以使用如下的二重指標代替一維陣列的指標進行型別轉換嗎?
auto f = new int[sz1 * sz2];
auto dp = (int **)f; /** 二重指標真的可以嗎?*/
若覺得可行的話,可能對二維陣列和二重指標的理解出現了偏差,試想,我們按照dp存盤的地址值a去尋址,得到地址a中存盤的值b,再按照值b去尋址的話會發生什么?(本例中,b的值的根本不是地址,而是陣列的值!)

我們思考后也不難理解,為什么宣告二維陣列的形參型別或者是強制型別轉換時,一定要正確指定最低維的大小,
方法2——分配一維陣列,以二維陣列的方式使用(推薦指數:???)
其實如果不是非要追求“傳統”的使用二維陣列的方式,也可以不用強制型別轉換的方法,
只需要把握一點:二維陣列的所有元素,在記憶體中是連續排列的,
那么我們可以按照如下的方式使用分配的二維陣列:
/** 假設需要根據兩個string的長度建立二維陣列 */
const int sz1 = str1.size();
const int sz2 = str2.size();
/** 動態分配記憶體 */
auto f = new int[sz1 * sz2];
/** 給每個元素賦值 */
for (int i = 0, idx = 1; i < sz1; ++i)
for (int j = 0; j < sz2; ++j, ++idx)
f[i * sz2 + j] = idx; /** 相當于 arr[i][j] = idx; */
/** 別忘記釋放堆疊空間 */
delete[] f;
f = nullptr;
與方法一大同小異,因此注意事項也一樣,注意f[i * sz2 + j]中sz2是最低維的大小,
方法3——多次動態分配(也需要多次釋放)(推薦指數:??)
簡單說,就是動態分配一維陣列,然后把這些陣列的指標存盤到一個陣列元素為一維陣列的陣列中,
代碼如下:
/** 假設需要根據兩個string的長度建立二維陣列 */
const int sz1 = str1.size();
const int sz2 = str2.size();
/** 分配一個陣列元素為一維陣列的陣列 */
auto dp = new int *[sz1];
/** 給陣列每個元素賦值 */
for (int i = 0; i < sz1; ++i)
dp[i] = new int[sz2];
/** 這里放置自己制造bug的操作*/
// abaabaaba
/** 制造完了別忘記釋放堆疊空間 */
for (int i = 0; i < sz1; ++i)
delete[] dp[i];
delete[] dp;
注意最后要先釋放元素的記憶體,
(小聲說,應該很少有人用這種方法?)
方法4——使用vector(推薦指數:?????)
前面的幾種方法多少是不太 idiomatic C++,最后當然要請出我們的STL,
沒什么說的,直接看代碼:
vector<vector<int> > dp(str1.length(), vector<int>(str2.length(), 0));
優點是不用再擔心記憶體釋放的問題,并且vector有很多方便的成員函式可以使用,
另外,在刷題的時候如果要判斷二維vector是否為空,可以使用如下陳述句:
if (dp.empty() || dp[0].empty())
return ;
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/549857.html
標籤:其他
下一篇:JdkProxy的進階知識
