1+ #include < stdio.h>
2+ #include < stdlib.h>
3+ #include < iostream>
4+ #include < string>
5+ #include < cstring>
6+ #include < random>
7+ #include < ctime>
8+ using namespace std ;
9+
10+ /* *
11+ * 跳表的一种实现方法。
12+ * 跳表中存储的是正整数,并且存储的是不重复的。
13+ *
14+ * 跳表的C++版本.
15+ * 翻译JAVA版本 原作者 Author:ZHENG
16+ *
17+ * Author:puhuaqiang
18+ *
19+ * 跳表结构:
20+ *
21+ * 第K级 1 9
22+ * 第K-1级 1 5 9
23+ * 第K-2级 1 3 5 7 9
24+ * ... ....
25+ * 第0级(原始链表) 1 2 3 4 5 6 7 8 9
26+ */
27+
28+ const int MAX_LEVEL = 16 ;
29+
30+ /* *
31+ * @brief 节点
32+ */
33+ class CNode
34+ {
35+ public:
36+ CNode ();
37+ ~CNode ();
38+
39+ std::string toString ();
40+ /* *
41+ * @brief 获取索引链表
42+ */
43+ CNode** GetIdxList ();
44+
45+ /* *
46+ * @brief 设置数据
47+ */
48+ void SetData (int v);
49+ /* *
50+ * @brief 获取数据
51+ */
52+ int GetData ();
53+ /* *
54+ * @brief 设置最大索引级别
55+ */
56+ void SetLevel (int l);
57+ private:
58+ /* *当前节点的值*/
59+ int m_data;
60+ /* *
61+ * 当前节点的每个等级的下一个节点.
62+ * 第2级 N1 N2
63+ * 第1级 N1 N2
64+ * 如果N1是本节点,则 m_lpForwards[x] 保存的是N2
65+ *
66+ * [0] 就是原始链表.
67+ */
68+ CNode* m_lpForwards[MAX_LEVEL];
69+ /* *当前节点的所在的最大索引级别*/
70+ int m_iMaxLevel;
71+ };
72+
73+ /* *
74+ * @brief 跳表
75+ */
76+ class CSkipList
77+ {
78+ public:
79+ CSkipList ();
80+ ~CSkipList ();
81+ /* *
82+ * @brief 查找指定的值的节点
83+ * @param v 正整数
84+ */
85+ CNode* Find (int v);
86+ /* *
87+ * @brief 插入指定的值
88+ * @param v 正整数
89+ */
90+ void Insert (int v);
91+ /* *
92+ * @brief 删除指定的值的节点
93+ * @param v 正整数
94+ */
95+ int Delete (int v);
96+ void PrintAll ();
97+ /* *
98+ * @brief 打印跳表结构
99+ * @param l 等于-1时打印所有级别的结构 >=0时打印指定级别的结构
100+ */
101+ void PrintAll (int l);
102+ /* *
103+ * @brief 插入节点时,得到插入K级的随机函数
104+ * @return K
105+ */
106+ int RandomLevel ();
107+
108+ private:
109+ int levelCount;
110+ /* *
111+ * 链表
112+ * 带头/哨所(节点)
113+ */
114+ CNode* m_lpHead;
115+ };
116+
117+ int main ()
118+ {
119+ CSkipList skipList;
120+ // / 插入原始值
121+ for (int i=1 ; i< 50 ; i++){
122+ if ((i%3 ) == 0 ){
123+ skipList.Insert (i);
124+ }
125+ }
126+ for (int i=1 ; i< 50 ; i++){
127+ if ((i%3 ) == 1 ){
128+ skipList.Insert (i);
129+ }
130+ }
131+ skipList.PrintAll ();
132+ std::cout<<std::endl;
133+ // / 打印所有等级结构
134+ skipList.PrintAll (-1 );
135+ // / 查找
136+ std::cout<<std::endl;
137+ CNode* lpNode = skipList.Find (27 );
138+ if (NULL != lpNode){
139+ std::cout<<" 查找值为27的节点,找到该节点,节点值:" <<lpNode->GetData ()<<std::endl;
140+ }else {
141+ std::cout<<" 查找值为27的节点,未找到该节点" <<std::endl;
142+ }
143+ // / 删除
144+ std::cout<<std::endl;
145+ int ret = skipList.Delete (46 );
146+ if (0 == ret){
147+ std::cout<<" 查找值为46的节点,找到该节点,并删除成功" <<std::endl;
148+ }else {
149+ std::cout<<" 查找值为46的节点,找到该节点,删除失败" <<std::endl;
150+ }
151+ std::cout<<std::endl;
152+ // 打印所有等级结构
153+ skipList.PrintAll (-1 );
154+ std::cin.ignore ();
155+ return 0 ;
156+ }
157+
158+ CNode::CNode ()
159+ {
160+ m_data = -1 ;
161+ m_iMaxLevel = 0 ;
162+ for (int i=0 ; i<MAX_LEVEL; i++){
163+ m_lpForwards[i] = NULL ;
164+ }
165+ }
166+ CNode::~CNode ()
167+ {
168+
169+ }
170+ CNode** CNode::GetIdxList ()
171+ {
172+ return m_lpForwards;
173+ }
174+
175+ void CNode::SetData (int v)
176+ {
177+ m_data = v;
178+ }
179+ int CNode::GetData ()
180+ {
181+ return m_data;
182+ }
183+ void CNode::SetLevel (int l)
184+ {
185+ m_iMaxLevel = l;
186+ }
187+ std::string CNode::toString ()
188+ {
189+ char tmp[32 ];
190+ std::string ret;
191+
192+ ret.append (" { data: " );
193+ sprintf (tmp, " %d" , m_data);
194+ ret.append (tmp);
195+ ret.append (" ; levels: " );
196+ sprintf (tmp, " %d" , m_iMaxLevel);
197+ ret.append (tmp);
198+ ret.append (" }" );
199+ return ret;
200+ }
201+
202+ CSkipList::CSkipList ()
203+ {
204+ levelCount = 1 ;
205+ m_lpHead = new CNode ();
206+ }
207+ CSkipList::~CSkipList ()
208+ {
209+
210+ }
211+ CNode* CSkipList::Find (int v)
212+ {
213+ CNode* lpNode = m_lpHead;
214+ /* *
215+ * 从 最大级索引链表开始查找.
216+ * K -> k-1 -> k-2 ...->0
217+ */
218+ for (int i=levelCount-1 ; i>=0 ; --i){
219+ /* *
220+ * 查找小于v的节点(lpNode).
221+ */
222+ while ((NULL != lpNode->GetIdxList ()[i]) && (lpNode->GetIdxList ()[i]->GetData () < v)){
223+ lpNode = lpNode->GetIdxList ()[i];
224+ }
225+ }
226+ /* *
227+ * lpNode 是小于v的节点, lpNode的下一个节点就等于或大于v的节点
228+ */
229+ if ((NULL != lpNode->GetIdxList ()[0 ]) && (lpNode->GetIdxList ()[0 ]->GetData () == v)){
230+ return lpNode->GetIdxList ()[0 ];
231+ }
232+ return NULL ;
233+ }
234+ void CSkipList::Insert (int v)
235+ {
236+ // / 新节点
237+ CNode* lpNewNode = new CNode ();
238+ if (NULL == lpNewNode){
239+ return ;
240+ }
241+
242+ /* *
243+ * 新节点最大分布在的索引链表的上限
244+ * 如果返回 3,则 新的节点会在索引1、2、3上的链表都存在
245+ */
246+ int level = RandomLevel ();
247+ lpNewNode->SetData (v);
248+ lpNewNode->SetLevel (level);
249+
250+ /* *
251+ * 临时索引链表
252+ * 主要是得到新的节点在每个索引链表上的位置
253+ */
254+ CNode *lpUpdateNode[level];
255+ for (int i=0 ; i<level; i++){
256+ // / 每个索引链表的头节点
257+ lpUpdateNode[i] =m_lpHead;
258+ }
259+ CNode* lpFind = m_lpHead;
260+ for (int i= level-1 ; i >= 0 ; --i){
261+ /* *
262+ * 查找位置
263+ * eg. 第1级 1 7 10
264+ * 如果插入的是 6
265+ * lpFind->GetIdxList()[i]->GetData() : 表示节点lpFind在第1级索引的下一个节点的数据
266+ * 当 "lpFind->GetIdxList()[i]->GetData() < v"不成立的时候,
267+ * 新节点就要插入到 lpFind节点的后面, lpFind->GetIdxList()[i] 节点的前面
268+ * 即在这里 lpFind就是1 lpFind->GetIdxList()[i] 就是7
269+ */
270+ while ((NULL != lpFind->GetIdxList ()[i]) && (lpFind->GetIdxList ()[i]->GetData () < v)){
271+ lpFind = lpFind->GetIdxList ()[i];
272+ }
273+ // / lpFind 是新节点在 第i级索引链表的后一个节点
274+ lpUpdateNode[i] = lpFind;
275+ }
276+
277+ for (int i=0 ; i<level; ++i){
278+ /* *
279+ * 重新设置链表指针位置
280+ * eg 第1级索引 1 7 10
281+ * 插入6.
282+ * lpUpdateNode[i] 节点是1; lpUpdateNode[i]->GetIdxList()[i]节点是7
283+ *
284+ * 这2句代码就是 把6放在 1和7之间
285+ */
286+ lpNewNode->GetIdxList ()[i] = lpUpdateNode[i]->GetIdxList ()[i];
287+ lpUpdateNode[i]->GetIdxList ()[i] = lpNewNode;
288+ }
289+ if (levelCount < level){
290+ levelCount = level;
291+ }
292+ }
293+ int CSkipList::Delete (int v)
294+ {
295+ int ret = -1 ;
296+ CNode *lpUpdateNode[levelCount];
297+ CNode *lpFind = m_lpHead;
298+ for (int i=levelCount-1 ; i>= 0 ; --i){
299+ /* *
300+ * 查找小于v的节点(lpFind).
301+ */
302+ while ((NULL != lpFind->GetIdxList ()[i]) && (lpFind->GetIdxList ()[i]->GetData () < v)){
303+ lpFind = lpFind->GetIdxList ()[i];
304+ }
305+ lpUpdateNode[i] = lpFind;
306+ }
307+ /* *
308+ * lpFind 是小于v的节点, lpFind的下一个节点就等于或大于v的节点
309+ */
310+ if ((NULL != lpFind->GetIdxList ()[0 ]) && (lpFind->GetIdxList ()[0 ]->GetData () == v)){
311+ for (int i=levelCount-1 ; i>=0 ; --i){
312+ if ((NULL != lpUpdateNode[i]->GetIdxList ()[i]) && (v == lpUpdateNode[i]->GetIdxList ()[i]->GetData ())){
313+ lpUpdateNode[i]->GetIdxList ()[i] = lpUpdateNode[i]->GetIdxList ()[i]->GetIdxList ()[i];
314+ ret = 0 ;
315+ }
316+ }
317+ }
318+ return ret;
319+ }
320+ void CSkipList::PrintAll ()
321+ {
322+ CNode* lpNode = m_lpHead;
323+ while (NULL != lpNode->GetIdxList ()[0 ]){
324+ std::cout<<lpNode->GetIdxList ()[0 ]->toString ().data ()<<std::endl;
325+ lpNode = lpNode->GetIdxList ()[0 ];
326+ }
327+ }
328+ void CSkipList::PrintAll (int l)
329+ {
330+ for (int i=MAX_LEVEL-1 ; i>=0 ;--i){
331+ CNode* lpNode = m_lpHead;
332+ std::cout<<" 第" <<i<<" 级:" <<std::endl;
333+ if ((l < 0 ) || ((l >= 0 ) && (l == i))){
334+ while (NULL != lpNode->GetIdxList ()[i]){
335+ std::cout<<lpNode->GetIdxList ()[i]->GetData ()<<" " ;
336+ lpNode = lpNode->GetIdxList ()[i];
337+ }
338+ std::cout<<std::endl;
339+ if (l >= 0 ){
340+ break ;
341+ }
342+ }
343+ }
344+ }
345+ int GetRandom ()
346+ {
347+ static int _count = 1 ;
348+ std::default_random_engine generator (time (0 ) + _count);
349+ std::uniform_int_distribution<int > distribution (1 ,99999 /* 0x7FFFFFFF*/ );
350+ int dice_roll = distribution (generator);
351+ _count += 100 ;
352+ return dice_roll;
353+ }
354+ int CSkipList::RandomLevel ()
355+ {
356+ int level = 1 ;
357+ for (int i=1 ; i<MAX_LEVEL; ++i){
358+ if (1 == (GetRandom ()%3 )){
359+ level++;
360+ }
361+ }
362+ return level;
363+ }
0 commit comments