C++二叉搜索樹圖片及代碼詳解
一. 概念
又稱二叉排序樹、二叉查找樹
性質(zhì)、判定:
1. 若它的左子樹不為空,則左子樹上所有節(jié)點(diǎn)的值都小于根節(jié)點(diǎn)的值
2. 若它的右子樹不為空,則右子樹上所有節(jié)點(diǎn)的值都大于根節(jié)點(diǎn)的值
3. 它的左右子樹都是二叉搜索樹
二. 實(shí)現(xiàn)
BinarySearchTree.h
template<class K>
struct BSTreeNode
{
BSTreeNode<K>* _left;
BSTreeNode<K>* _right;
K _key;
BSTreeNode(const K& key)
:_left(nullptr)
, _right(nullptr)
, _key(key)
{ }
};
template<class K>
class BSTree
{
typedef BSTreeNode<K> Node;
public:
BSTree()
:_root(nullptr)
{ }
bool Insert(const K& key) {}
bool Find(const K& key) {}
bool Erase(const K& key) {}
void InOrder() {}
private:
void _InOrder(Node* root) {}
private:
Node* _root;
};
void TestBSTree1()
{
int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };
BSTree<int> t;
for (auto e : a)
{
t.Insert(e);
}
t.InOrder();
t.Erase(4);
t.InOrder();
t.Erase(6);
t.InOrder();
t.Erase(7);
t.InOrder();
t.Erase(3);
t.InOrder();
for (auto e : a)
{
t.Erase(e);
}
t.InOrder();
}1. 查找
從根開始比較,查找,比根大則往右邊走查找,比根小則往左邊走查找
最多找高度次:O(N)

紅黑樹、AVL樹:O(logN)
bool Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (cur->_key < key)
{
cur = cur->_right;
}
else if (cur->_key > key)
{
cur = cur->_left;
}
else
{
return true;
}
}
return false;
}2. 插入
樹為空,則直接新增節(jié)點(diǎn),賦值給 root 指針
樹不空,按二叉搜索樹性質(zhì)查找插入位置,插入新節(jié)點(diǎn)

bool Insert(const K& key)
{
if (_root == nullptr)
{
_root = new Node(key);
return true;
}
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else
{
return false;
}
}
cur = new Node(key);
if (parent->_key < key)
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
return true;
}3. 中序遍歷
中序遍歷(左子樹、根、右子樹)二叉搜索樹的結(jié)果是排序的結(jié)果
void InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
InOrder(root->_left);
cout << root->_key << " ";
InOrder(root->_right);
}有問題,我們?cè)谕饷嬗脤?duì)象調(diào)用中序遍歷要傳私有成員變量 _root,但是私有我們不能在類外面用
BSTree<int> t; t.InOrder();
可以這樣解決:
void InOrder()
{
_InOrder(_root);
cout << endl;
}
void _InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
_InOrder(root->_left);
cout << root->_key << " ";
_InOrder(root->_right);
}4. 刪除
要?jiǎng)h的節(jié)點(diǎn)有3種情況:
1. 沒有孩子:托孤
2. 有1個(gè)孩子:托孤
3. 有2個(gè)孩子:和左子樹的最大節(jié)點(diǎn)(左子樹的最右節(jié)點(diǎn)) 或 右子樹的最小節(jié)點(diǎn)(右子樹的最左節(jié)點(diǎn)) 替換

bool Erase(const K& key)
{
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else // 樹中找到了要?jiǎng)h除的節(jié)點(diǎn)cur
{
// ......
delete cur;
return true;
}
}
return false;
}cur 左為空(也解決了沒有孩子,左右都為空):

else // 樹中找到了要?jiǎng)h除的節(jié)點(diǎn)cur
{
// cur左為空
if (cur->_left == nullptr)
{
if (parent->_right == cur)
{
parent->_right = cur->_right;
}
else
{
parent->_left = cur->_right;
}
}
// ......
delete cur;
return true;
}但有這種特殊情況:

else // 樹中找到了要?jiǎng)h除的節(jié)點(diǎn)cur
{
// cur左為空
if (cur->_left == nullptr)
{
if (cur == _root)
{
_root = cur->_right;
}
else
{
if (parent->_right == cur)
{
parent->_right = cur->_right;
}
else
{
parent->_left = cur->_right;
}
}
}
// ......
delete cur;
return true;
}cur 右為空:同理

else // 樹中找到了要?jiǎng)h除的節(jié)點(diǎn)cur
{
// cur左為空
if (cur->_left == nullptr) { }
// cur右為空
else if (cur->_right == nullptr)
{
if (cur == _root)
{
_root = cur->_left;
}
else
{
if (parent->_right == cur)
{
parent->_right = cur->_left;
}
else // parent->_left == cur
{
parent->_left = cur->_left;
}
}
}
// ......
delete cur;
return true;
}cur 左右都不為空:替換 以左子樹的最大節(jié)點(diǎn)(左子樹的最右節(jié)點(diǎn))為例

注意:leftMax 是左子樹的最右節(jié)點(diǎn),leftMax 這個(gè)節(jié)點(diǎn)一定不會(huì)有右子樹,可能有左子樹
注意:
這里是左右都不為空的情況,而且我們要去左子樹找最右節(jié)點(diǎn),所以 leftMax 可直接定義為 cur->_left;parent 可直接定義為 cur
如果 leftMax 定義為 cur,parent 定義為 nullptr,例3會(huì)坑

注意:替換后要通過找到父親直接刪(一定可以直接刪,因?yàn)?leftMax 右一定為空)。不能遞歸刪(7 < 8,在右子樹找,找不到,刪不了)。因?yàn)樗阉鳂涞慕Y(jié)構(gòu)變了,而且無法傳根,無法控制;進(jìn)而導(dǎo)致不滿足二叉搜索樹的性質(zhì)

else // 樹中找到了要?jiǎng)h除的節(jié)點(diǎn)cur
{
// cur左為空
if (cur->_left == nullptr) { }
// cur右為空
else if (cur->_right == nullptr) { }
// cur左右都不為空
else
{
// 找替代節(jié)點(diǎn)
Node* parent = cur;
Node* leftMax = cur->_left;
while (leftMax->_right)
{
parent = leftMax;
leftMax = leftMax->_right;
}
swap(cur->_key, leftMax->_key);
if (parent->_left == leftMax)
{
parent->_left = leftMax->_left;
}
else // parent->_right == leftMax
{
parent->_right = leftMax->_left;
}
cur = leftMax;
}
delete cur;
return true;
}三. 遞歸版實(shí)現(xiàn)
C++里,凡是樹形結(jié)構(gòu)遞歸,都要單獨(dú)寫子函數(shù)。因?yàn)檫f歸是子問題,要控制子樹
BinarySearchTree.h
template<class K>
struct BSTreeNode
{
BSTreeNode<K>* _left;
BSTreeNode<K>* _right;
K _key;
BSTreeNode(const K& key)
:_left(nullptr)
, _right(nullptr)
, _key(key)
{ }
};
template<class K>
class BSTree
{
typedef BSTreeNode<K> Node;
public:
BSTree()
:_root(nullptr)
{ }
void InOrder()
{
_InOrder(_root);
cout << endl;
}
bool FindR(const K& key)
{
return _FindR(_root, key);
}
bool InsertR(const K& key)
{
return _InsertR(_root, key);
}
bool EraseR(const K& key)
{
return _EraseR(_root, key);
}
private:
bool _FindR(Node* root, const K& key) {}
bool _InsertR(Node*& root, const K& key) {}
bool _EraseR(Node*& root, const K& key) {}
void _InOrder(Node* root) {}
private:
Node* _root;
};1. 查找
比根大,在右子樹找;比根小,在左子樹找;到空還沒找到,則不存在
bool FindR(const K& key)
{
return _FindR(_root, key);
}
bool _FindR(Node* root, const K& key)
{
if (root == nullptr)
return false;
if (root->_key < key)
{
return _FindR(root->_right, key);
}
else if (root->_key > key)
{
return _FindR(root->_left, key);
}
else
{
return true;
}
}2. 插入
插入的值 < 根:往左子樹去插入
插入的值 > 根:往右子樹去插入
插入的值 == 根:插入失敗
走到空的地方就可以插入
怎么插入?new Node(key),但還要找父親,怎么解決?加引用成為 Node*& root
這里指針的作用:鏈接樹
這里引用的作用:下一層改變影響上一層
bool InsertR(const K& key)
{
return _InsertR(_root, key);
}
bool _InsertR(Node*& root, const K& key)
{
if (root == nullptr)
{
root = new Node(key);
return true;
}
if (root->_key < key)
{
return _InsertR(root->_right, key);
}
else if (root->_key > key)
{
return _InsertR(root->_left, key);
}
else
{
return false;
}
}如果是空樹,root 是 _root 的別名,new 的第一個(gè)節(jié)點(diǎn)剛好給 _root
如果不是空樹,層層往下遞歸,前面的引用不起作用,每一層(每一個(gè)棧幀)都有一個(gè)引用

6 是對(duì)象,把左指針這個(gè)成員傳給下一層,下一層的 root 是 6 的左指針的別名(引用此時(shí)不發(fā)揮作用)
5 > 4,把 4 的右指針往下傳,root 是 4 的右指針的別名
4 的右指針為空 ==> 插入
new節(jié)點(diǎn),給 root,對(duì) root 修改,就是對(duì) 4 的右指針修改
這一句賦值,直接就鏈接上了,不用找父親,不用比較大小

3. 刪除
先找有沒有要?jiǎng)h的節(jié)點(diǎn),找到了就刪,同樣分3種情況:左為空、右為空、左右都為空
bool EraseR(const K& key)
{
return _EraseR(_root, key);
}
bool _EraseR(Node*& root, const K& key)
{
if (root == nullptr) // 樹里沒有
return false;
if (root->_key < key)
{
return _EraseR(root->_right, key);
}
else if (root->_key > key)
{
return _EraseR(root->_left, key);
}
else // 找到了,準(zhǔn)備刪
{
Node* del = root;
if (root->_left == nullptr) // 1.左為空
{
root = root->_right;
}
else if (root->_right == nullptr) // 2.右為空
{
root = root->_left;
}
else // 3. 左右都不為空
{ }
delete del;
return true;
}
}
3 < 6,3 的右指針往下傳,root 是 3 的右指針的別名
此時(shí) root 是 6,找到了,開始刪:root 左為空,把 root(3的右指針)賦值為 root 的右指針
root 的右指針指向 7 ==> 3 的右指針指向 7,完成了鏈接關(guān)系

root 是 _root 的別名,上來就找到了,開始刪:
root 不為空,root = root->_right 就是 _root = _root->_right;
左右都為空:找替代節(jié)點(diǎn)(以找左樹的最右節(jié)點(diǎn)為例,最右節(jié)點(diǎn)的右一定為空)
以剛開始就找到要?jiǎng)h的 8 為例:
轉(zhuǎn)化為刪紅圈的節(jié)點(diǎn)。非遞歸實(shí)現(xiàn)一定可以找父親,直接刪;不能遞歸刪

我們現(xiàn)在有了引用,root 是 _root 的別名
但在 root 當(dāng)前位置發(fā)揮不了作用,因?yàn)椴恍枰?_root,所以不能直接在最大的樹刪除
可以轉(zhuǎn)化為在藍(lán)圈的樹中刪,遞歸往下走,一定是右為空的情況。那時(shí),root 是 6 的右指針的別名
走這個(gè)情形:

else // 3. 左右都不為空
{
Node* leftMax = root->_left;
while (leftMax->_right)
{
leftMax = leftMax->_right;
}
swap(root->_key, leftMax->_key);
return _EraseR(root->_left, key);
}這種方法在替換后,會(huì)在左子樹再找一遍要?jiǎng)h除的節(jié)點(diǎn),但代價(jià)不大
第11行遞歸進(jìn)去之后,不會(huì)再次走這個(gè)左右都不為空的 else
4. 析構(gòu)、拷貝、賦值
析構(gòu):析構(gòu)也得寫子函數(shù),因?yàn)橐f歸,析構(gòu)函數(shù)都沒有參數(shù)
二叉樹:用后序遍歷刪除,循環(huán)不好用
拷貝:不能調(diào) Insert,會(huì)改變樹的形狀
走前序遍例賦值
默認(rèn)的拷貝構(gòu)造是淺拷貝,會(huì)出錯(cuò),要自己實(shí)現(xiàn)深拷貝
賦值:現(xiàn)代寫法
BSTree(const BSTree<K>& t)
{
_root = Copy(t._root);
}
BSTree<K>& operator=(BSTree<K> t)
{
swap(_root, t._root);
return *this;
}
~BSTree()
{
Destroy(_root);
}
void Destroy(Node*& root)
{
if (root == nullptr)
return;
Destroy(root->_left);
Destroy(root->_right);
delete root;
root = nullptr; // 這就是傳引用的原因
}
Node* Copy(Node* root)
{
if (root == nullptr)
return nullptr;
Node* copyroot = new Node(root->_key);
copyroot->_left = Copy(root->_left);
copyroot->_right = Copy(root->_right);
return copyroot;
}非遞歸+遞歸整體代碼
template<class K>
struct BSTreeNode
{
BSTreeNode<K>* _left;
BSTreeNode<K>* _right;
K _key;
BSTreeNode(const K& key)
:_left(nullptr)
, _right(nullptr)
, _key(key)
{ }
};
template<class K>
class BSTree
{
typedef BSTreeNode<K> Node;
public:
BSTree()
:_root(nullptr)
{ }
BSTree(const BSTree<K>& t)
{
_root = Copy(t._root);
}
BSTree<K>& operator=( BSTree<K> t)
{
swap(_root, t._root);
return *this;
}
~BSTree()
{
Destroy(_root);
}
bool Insert(const K& key)
{
if (_root == nullptr)
{
_root = new Node(key);
return true;
}
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else
{
return false;
}
}
cur = new Node(key);
if (parent->_key < key)
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
return true;
}
bool Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (cur->_key < key)
{
cur = cur->_right;
}
else if (cur->_key > key)
{
cur = cur->_left;
}
else
{
return true;
}
}
return false;
}
bool Erase(const K& key)
{
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else // 樹中找到了要?jiǎng)h除的節(jié)點(diǎn)cur
{
// cur左為空
if (cur->_left == nullptr)
{
if (cur == _root)
{
_root = cur->_right;
}
else
{
if (parent->_right == cur)
{
parent->_right = cur->_right;
}
else // parent->_left == cur
{
parent->_left = cur->_right;
}
}
}
// cur右為空
else if (cur->_right == nullptr)
{
if (cur == _root)
{
_root = cur->_left;
}
else
{
if (parent->_right == cur)
{
parent->_right = cur->_left;
}
else // parent->_left == cur
{
parent->_left = cur->_left;
}
}
}
// cur左右都不為空
else
{
// 找替代節(jié)點(diǎn)
Node* parent = cur;
Node* leftMax = cur->_left;
while (leftMax->_right)
{
parent = leftMax;
leftMax = leftMax->_right;
}
swap(cur->_key, leftMax->_key);
if (parent->_left == leftMax)
{
parent->_left = leftMax->_left;
}
else // parent->_right == leftMax
{
parent->_right = leftMax->_left;
}
cur = leftMax;
}
delete cur;
return true;
}
}
return false;
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
bool FindR(const K& key)
{
return _FindR(_root, key);
}
bool InsertR(const K& key)
{
return _InsertR(_root, key);
}
bool EraseR(const K& key)
{
return _EraseR(_root, key);
}
private:
void Destroy(Node*& root)
{
if (root == nullptr)
return;
Destroy(root->_left);
Destroy(root->_right);
delete root;
root = nullptr; // 這就是傳引用的原因
}
Node* Copy(Node* root)
{
if (root == nullptr)
return nullptr;
Node* copyroot = new Node(root->_key);
copyroot->_left = Copy(root->_left);
copyroot->_right = Copy(root->_right);
return copyroot;
}
bool _FindR(Node* root, const K& key)
{
if (root == nullptr)
return false;
if (root->_key < key)
{
return _FindR(root->_right, key);
}
else if (root->_key > key)
{
return _FindR(root->_left, key);
}
else
{
return true;
}
}
bool _InsertR(Node*& root, const K& key)
{
if (root == nullptr)
{
root = new Node(key);
return true;
}
if (root->_key < key)
{
return _InsertR(root->_right, key);
}
else if (root->_key > key)
{
return _InsertR(root->_left, key);
}
else
{
return false;
}
}
bool _EraseR(Node*& root, const K& key)
{
if (root == nullptr) // 樹里沒有
return false;
if (root->_key < key)
{
return _EraseR(root->_right, key);
}
else if (root->_key > key)
{
return _EraseR(root->_left, key);
}
else // 找到了,準(zhǔn)備刪
{
Node* del = root;
if (root->_left == nullptr) // 1.左為空
{
root = root->_right;
}
else if (root->_right == nullptr) // 2.右為空
{
root = root->_left;
}
else // 3. 左右都不為空
{
Node* leftMax = root->_left;
while (leftMax->_right)
{
leftMax = leftMax->_right;
}
swap(root->_key, leftMax->_key);
return _EraseR(root->_left, key);
}
delete del;
return true;
}
}
void _InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
_InOrder(root->_left);
cout << root->_key << " ";
_InOrder(root->_right);
}
private:
Node* _root;
};
void TestBSTree1()
{
int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };
BSTree<int> t;
for (auto e : a)
{
t.InsertR(e);
}
t.InOrder();
t.EraseR(4);
t.InOrder();
t.EraseR(6);
t.InOrder();
t.EraseR(7);
t.InOrder();
t.EraseR(3);
t.InOrder();
for (auto e : a)
{
t.EraseR(e);
}
t.InOrder();
}
void TestBSTree2()
{
int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };
BSTree<int> t;
for (auto e : a)
{
t.InsertR(e);
}
BSTree<int> t1(t);
t.InOrder();
t1.InOrder();
}四. 應(yīng)用模型
1. key 的搜索模型
快速判斷在不在的場(chǎng)景
門禁系統(tǒng)、小區(qū)車輛出入系統(tǒng) ……
2. key_value 的搜索模型
通過一個(gè)值找另一個(gè)值
商場(chǎng)的車輛出入系統(tǒng)、高鐵實(shí)名制車票系統(tǒng) ……
namespace key_value
{
template<class K, class V>
struct BSTreeNode
{
BSTreeNode<K, V>* _left;
BSTreeNode<K, V>* _right;
K _key;
V _value;
BSTreeNode(const K& key, const V& value)
:_left(nullptr)
, _right(nullptr)
, _key(key)
, _value(value)
{ }
};
template<class K, class V>
class BSTree
{
typedef BSTreeNode<K, V> Node;
public:
BSTree()
:_root(nullptr)
{ }
void InOrder()
{
_InOrder(_root);
cout << endl;
}
Node* FindR(const K& key)
{
return _FindR(_root, key);
}
bool InsertR(const K& key, const V& value)
{
return _InsertR(_root, key, value);
}
bool EraseR(const K& key)
{
return _EraseR(_root, key);
}
private:
Node* _FindR(Node* root, const K& key)
{
if (root == nullptr)
return nullptr;
if (root->_key < key)
{
return _FindR(root->_right, key);
}
else if (root->_key > key)
{
return _FindR(root->_left, key);
}
else
{
return root;
}
}
bool _InsertR(Node*& root, const K& key, const V& value)
{
if (root == nullptr)
{
root = new Node(key, value);
return true;
}
if (root->_key < key)
{
return _InsertR(root->_right, key, value);
}
else if (root->_key > key)
{
return _InsertR(root->_left, key, value);
}
else
{
return false;
}
}
bool _EraseR(Node*& root, const K& key)
{
if (root == nullptr) // 樹里沒有
return false;
if (root->_key < key)
{
return _EraseR(root->_right, key);
}
else if (root->_key > key)
{
return _EraseR(root->_left, key);
}
else // 找到了,準(zhǔn)備刪
{
Node* del = root;
if (root->_left == nullptr) // 1.左為空
{
root = root->_right;
}
else if (root->_right == nullptr) // 2.右為空
{
root = root->_left;
}
else // 3. 左右都不為空
{
Node* leftMax = root->_left;
while (leftMax->_right)
{
leftMax = leftMax->_right;
}
swap(root->_key, leftMax->_key);
return _EraseR(root->_left, key);
}
delete del;
return true;
}
}
void _InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
_InOrder(root->_left);
cout << root->_key << ":" << root->_value << endl;
_InOrder(root->_right);
}
private:
Node* _root;
};
}拼寫檢查:讀取詞庫放到一顆搜索樹;讀取單詞,看在不在樹中,不在則拼寫錯(cuò)誤
void TestBSTree1()
{
BSTree<string, string> dict;
dict.InsertR("hello", "你好");
dict.InsertR("tree", "樹");
dict.InsertR("apple", "蘋果");
dict.InsertR("day", "天");
string str;
while (cin >> str)
{
BSTreeNode<string, string>* ret = dict.FindR(str);
if (ret != nullptr)
{
cout << ret->_value << endl;
}
else
{
cout << "沒有此單詞" << endl;
}
}
}
統(tǒng)計(jì)出現(xiàn)次數(shù)
void TestBSTree2()
{
string arr[] = { "蘋果", "西瓜", "蘋果", "西瓜", "蘋果",
"蘋果", "西瓜", "蘋果", "香蕉", "蘋果", "香蕉" };
BSTree<string, int> countTree;
for (auto& str : arr)
{
BSTreeNode<string, int>* ret = countTree.FindR(str);
if (ret == nullptr)
{
countTree.InsertR(str, 1);
}
else
{
ret->_value++;
}
}
countTree.InOrder();
}
總結(jié)
到此這篇關(guān)于C++二叉搜索樹詳解的文章就介紹到這了,更多相關(guān)C++二叉搜索樹內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++輕松實(shí)現(xiàn)字符串與字符數(shù)組的相互轉(zhuǎn)換
本文詳細(xì)介紹了如何在C++中通過c_str()和strcpy()函數(shù)將字符串轉(zhuǎn)換為字符數(shù)組,以及使用for循環(huán)、+運(yùn)算符、重載=和內(nèi)置構(gòu)造函數(shù)將字符數(shù)組轉(zhuǎn)換為字符串的方法,需要的朋友可以參考下2025-03-03
OpenCV實(shí)現(xiàn)直線檢測(cè)并消除
這篇文章主要為大家詳細(xì)介紹了OpenCV實(shí)現(xiàn)直線檢測(cè)并消除,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06
VS2019簡(jiǎn)單快速的打包可安裝項(xiàng)目(圖文教程)
這篇文章主要介紹了VS2019簡(jiǎn)單快速的打包可安裝項(xiàng)目,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03
C/C++實(shí)現(xiàn)快速排序(兩種方式)圖文詳解
這篇文章主要介紹了C/C++實(shí)現(xiàn)快速排序的方法,這幾天在找工作,被問到快速排序,結(jié)果想不出來快速排序怎么弄的;回來搜索了一下,現(xiàn)在記錄下來,方便以后查看2021-08-08

