链表的一些常用操作

  1 // LinkListDemo.cpp : Defines the entry point for the console application.
  2 //
  3
  4 #include "stdafx.h"
  5
  6 #include <iostream>
  7 #include <assert.h>
  8 using namespace std;
  9
 10 #define random(x) (rand()%x)
 11
 12 #define INVALIDVALUE -1000000000
 13
 14 typedef struct LNode
 15 {
 16     int data;
 17     LNode* pnext;
 18     LNode(){data = INVALIDVALUE; pnext = NULL;}
 19 }BINODE, *PBINODE;
 20
 21 class CLinkList
 22 {
 23 public:
 24     CLinkList();
 25     ~CLinkList();
 26
 27 private:
 28     CLinkList(const CLinkList &rh);
 29     CLinkList& operator=(const CLinkList &rh);
 30
 31 public:
 32
 33     //
 34     // 函数功能:获取链表中元素个数
 35     int getcount();
 36
 37     //
 38     // 函数功能:清空链表
 39     void clear();
 40
 41     //
 42     // 函数功能:获取链表第nPos个位置上的结点指针
 43     PBINODE getnode(int nPos);
 44
 45     //
 46     // 函数功能:获取中间结点
 47     // 注:这个获取的方式是通过连个指针,一个步长为1,另一个步长为2.步长为2的走到底后步长为1的正好到中间
 48     int getmid();
 49
 50     //
 51     // 函数功能:获取根结点
 52     PBINODE getroot();
 53
 54     //
 55     // 函数功能:在nPos位置上插入元素
 56     bool insertnode(PBINODE pNode, int nPos);
 57
 58     //
 59     // 函数功能:在nPos位置上插入元素
 60     bool insertnode(int value, int nPos);
 61
 62     //
 63     // 函数功能:删除第nPos位置上的元素
 64     bool deletenode(int nPos);
 65
 66     //
 67     // 函数功能:打印链表
 68     void printnode();
 69
 70     //
 71     // 函数功能:值为nValue元素的第n次出现的位置
 72     int locate(int nvalue,int n);
 73
 74     //
 75     // 函数功能:逆置
 76     void reverse();
 77
 78     //
 79     // 函数功能:排序(冒泡排序法)
 80     void BubbleSort();
 81
 82 private:
 83     PBINODE m_root;
 84     int m_nCount;
 85 };
 86
 87 CLinkList::CLinkList()
 88 {
 89     m_root = new LNode();
 90     m_nCount = 0;
 91     assert(m_root != NULL);
 92 }
 93
 94 CLinkList::~CLinkList()
 95 {
 96     clear();
 97 }
 98
 99 //
100 // 函数功能:获取链表中元素个数
101 int CLinkList::getcount()
102 {
103     return m_nCount;
104 }
105
106 //
107 // 函数功能:清空链表
108 void CLinkList::clear()
109 {
110     PBINODE pNode = m_root;
111     PBINODE ptmpNode = NULL;
112     while(pNode != NULL)
113     {
114         ptmpNode = pNode->pnext;
115         delete pNode;
116         pNode = ptmpNode;
117     }
118     m_root = NULL;
119 }
120
121 //
122 // 函数功能:获取根结点
123 PBINODE CLinkList::getroot()
124 {
125     return m_root;
126 }
127
128 //
129 // 函数功能:获取链表第nPos个位置上的结点指针
130 PBINODE CLinkList::getnode(int npos)
131 {
132     if (m_root == NULL)
133     {
134         return NULL;
135     }
136
137     if (npos > getcount())
138     {
139         return NULL;
140     }
141
142     PBINODE pNode = m_root;
143     int i = 0;
144     while (i < npos)
145     {
146         pNode = pNode->pnext;
147         i++;
148     }
149     return pNode;
150 }
151
152 //
153 // 函数功能:获取中间结点
154 // 注:这个获取的方式是通过连个指针,一个步长为1,另一个步长为2.步长为2的走到底后步长为1的正好到中间
155 int  CLinkList::getmid()
156 {
157     /*
158     // 方法一,通过对象本身的个数来求中间的元素
159     if (getcount() <= 1)
160     {
161         return INVALIDVALUE;
162     }
163
164     int nMid = getcount() / 2;
165
166     PBINODE pNode = getnode(nMid);
167     assert(pNode != NULL);
168
169     return pNode->data;
170     */
171
172     PBINODE pNode = getroot();
173     PBINODE pTNode = pNode->pnext;
174     while (pTNode != NULL)
175     {
176         pNode = pNode->pnext;
177         pTNode = pTNode->pnext;
178         if (pTNode != NULL)
179         {
180             pTNode = pTNode->pnext;
181         }
182     }
183     assert(pNode != NULL);
184     return pNode->data;
185 }
186
187 //
188 // 函数功能:在nPos位置上插入元素
189 bool CLinkList::insertnode(PBINODE pNode, int nPos)
190 {
191     if (pNode == NULL || nPos <= 0 || nPos > getcount() + 1)
192     {
193         return false;
194     }
195
196     PBINODE pPreNode = getnode(nPos - 1);
197     assert(pPreNode != 0);
198     PBINODE ptmp = pPreNode->pnext;
199     pPreNode->pnext = pNode;
200     pNode->pnext = ptmp;
201     m_nCount++;
202
203     return true;
204 }
205
206 //
207 // 函数功能:在nPos位置上插入元素
208 bool CLinkList::insertnode(int value, int nPos)
209 {
210     if (nPos <= 0 || nPos > getcount() + 1)
211     {
212         return false;
213     }
214
215     PBINODE pNode = new LNode();
216     assert(pNode != NULL);
217     pNode->data = value;
218
219     PBINODE pPreNode = getnode(nPos - 1);
220     assert(pPreNode != NULL);
221
222     PBINODE ptmp = pPreNode->pnext;
223
224     pPreNode->pnext = pNode;
225     pNode->pnext = ptmp;
226
227     m_nCount++;
228
229     return true;
230 }
231
232 //
233 // 函数功能:删除第nPos位置上的元素
234 bool CLinkList::deletenode(int nPos)
235 {
236     if (nPos <= 0 || nPos > getcount())
237     {
238         return false;
239     }
240
241     PBINODE pNode = getnode(nPos - 1);
242     assert(pNode != NULL);
243     PBINODE pDNode = pNode->pnext;
244     assert(pDNode != NULL);
245     pNode->pnext = pDNode->pnext;
246
247     delete pDNode;
248     pDNode = NULL;
249
250     return true;
251 }
252
253 //
254 // 函数功能:打印链表
255 void CLinkList::printnode()
256 {
257     PBINODE root = getroot();
258     PBINODE pNode = root->pnext;
259     while(pNode != NULL)
260     {
261         cout<< pNode->data<< " ";
262         pNode = pNode->pnext;
263     }
264     cout<<endl;
265 }
266
267 //
268 // 函数功能:值为nValue元素的第n次出现的位置
269 int CLinkList::locate(int nvalue,int n)
270 {
271     PBINODE root = getroot();
272     PBINODE pNode = root->pnext;
273     int i = 0;
274
275     int nNum = 0;
276     while (pNode != NULL /*&& pNode->data != nvalue*/)
277     {
278         if (pNode->data == nvalue)
279         {
280             nNum++;
281         }
282         pNode = pNode->pnext;
283         i++;
284         if (nNum == n)
285         {
286             break;
287         }
288     }
289
290     if (pNode == NULL)
291     {
292         return 0;
293     }
294     else
295     {
296         return i;
297     }
298
299 }
300
301 //
302 // 函数功能:逆置
303 void CLinkList::reverse()
304 {
305     PBINODE root = getroot();
306     assert(root != NULL);
307
308     PBINODE prenode = root->pnext;
309     assert(prenode != NULL);
310
311     PBINODE curnode = prenode->pnext;
312     prenode->pnext = NULL;
313     while (curnode != NULL)
314     {
315         PBINODE nextnode = curnode->pnext;
316         curnode->pnext = prenode;
317         prenode = curnode;
318         curnode = nextnode;
319     }
320
321     root->pnext = prenode;
322 }
323
324 //
325 // 函数功能:排序(冒泡排序法)
326 void CLinkList::BubbleSort()
327 {
328     PBINODE root = getroot();
329     assert(root != NULL);
330
331     for (int i = 0; i < getcount(); i++)
332     {
333         PBINODE pNode = root->pnext;
334         for (int j = 0; j < getcount() - i; j++)
335         {
336             PBINODE pNodeNext = pNode->pnext;
337             if (pNodeNext == NULL)
338             {
339                 break;
340             }
341             if (pNode->data > pNodeNext->data)
342             {
343                 int tmp = pNode->data;
344                 pNode->data = pNodeNext->data;
345                 pNodeNext->data =  tmp;
346             }
347             pNode = pNode->pnext;
348             if (pNode == NULL)
349             {
350                 break;
351             }
352         }
353     }
354 }
355
356 //已知指针la和lb分别指向两个链表。下列算法是从表la中删除自第i个元素起共len个元素后,将它们插入到表lb中第i个元素之前。
357 void DeleteAndInsertSub(CLinkList &la, CLinkList &lb, int i, int len)
358 {
359     if (i + len - 1 > la.getcount() || i <= 0 || len < 0 || i > lb.getcount())
360     {
361         return;
362     }
363
364     if (la.getroot() == lb.getroot())
365     {
366         return;
367     }
368
369     PBINODE pLa = la.getnode(i);
370     if (pLa == NULL)
371     {
372         return;
373     }
374
375     int nCount = 0;
376     while (nCount < len && pLa != NULL)
377     {
378         int nvalue = pLa->data;
379         lb.insertnode(nvalue, i + nCount);
380         pLa = pLa->pnext;
381         nCount++;
382     }
383 }
384
385 //已知两个链表head1 和head2 各自有序,请把它们合并成一个链表依然有序
386 void Merge(CLinkList &la, CLinkList &lb)
387 {
388
389 }
390
391 //如何检查一个单向链表上是否有环,同样两个指针,一个步长为1,另一个步长为2,如果两个指针能相遇则有环。
392 bool IsCircle(const CLinkList &la)
393 {
394
395 }
396
397 //只给定单链表中某个结点p(并非最后一个结点,即p->next!=NULL)指针,删除该结点。将p后面那个节点的值复制到p,删除p后面的节点
398 void DeleteNode(int nPos)
399 {
400
401 }
402
403 //在p前面插入一个节点 。在p后面插入新节点,将p的值与新建的节点值互换。
404 void InsertNode(int nPos)
405 {
406
407 }
408
409 //给定单链表头结点,删除链表中倒数第k个结点. 一个指针指向链表头,另一个指针指向第k个指针,然后两个指针一起移动,第二个指针到了末端则第一个指针就是倒数第k个节点
410 void ReverseDelete(int npos)
411 {
412
413 }
414
415 //判断两个链表是否相交。两种情况,如果链表有环,则先在环里设定一个指针不动,另一个链表从头开始移动,如果另一个链表能够与环中的指针相遇则是相交。如果没有环,则判断两个链表的最后个节点是否相同,相同则相交
416 bool IsCross(const CLinkList &la, const CLinkList &lb)
417 {
418
419 }
420
421 //两个链表相交,找出交点求出两个链表的长度a和b,一个指针指向较短链表的头head,另一个指针指向较长链表的第head+|a-b|,然后两个指针一起移动,相遇处即为交点。
422 int CrossNode(const CLinkList &la, const CLinkList &lb)
423 {
424
425 }
426
427 int _tmain(int argc, _TCHAR* argv[])
428 {
429     CLinkList link1;
430
431     cout<<"初始化链表link1:"<<endl;
432     int i = 0;
433     for (i = 1; i <= 15; i++)
434     {
435         int val = random(100);
436         if (!link1.insertnode(val, i))
437         {
438             return 0;
439         }
440     }
441
442     link1.insertnode(41, 10);
443     link1.printnode();
444     cout<<"link1链表长度为:"<<link1.getcount()<<endl;
445     cout << "41在link1中第2次出现的位置:"<<link1.locate(41, 2)<<endl;
446     cout<<"link1链表逆序为:"<<endl;
447     link1.reverse();
448     link1.printnode();
449     cout<<endl;
450
451     CLinkList link2;
452     cout<<"初始化链表link2:"<<endl;
453     for (i = 1; i <= 20; i++)
454     {
455         int val = random(100);
456         if (!link2.insertnode(val, i))
457         {
458             return 0;
459         }
460     }
461     link2.insertnode(41, 17);
462     link2.printnode();
463     cout<<"link2链表长度为:"<<link2.getcount()<<endl;
464
465     DeleteAndInsertSub(link1, link2, 3, 3);
466     link2.printnode();
467     cout<<"修改后link2链表长度为:"<<link2.getcount()<<endl;
468
469     cout<<endl<<"两个链表进行排序,排序后显示:"<<endl;
470     link1.BubbleSort();
471     link1.printnode();
472
473     link2.BubbleSort();
474     link2.printnode();
475
476     cout<<"获取link1的中间元素:";
477     cout<<link1.getmid()<<endl;
478     return 0;
479 }

时间: 2024-10-10 08:00:39

链表的一些常用操作的相关文章

Java数据结构系类之——链表(1):单链表及相关常用操作

package LinkList; public class Node<T> { public T data;//数据域 public Node next;//结点域 //默认构造方法 public Node(){ } //带参构造方法,非头结点初始化 public Node(T data,Node next){ this.data=data; this.next=next; } //头结点初始化 public Node(Node next){ this.next=next; } //显示结点

复习一下单链表的常用操作

复习一下单链表的常用操作,包括单链表的创建.插入.删除.排序.逆置以及打印输出等. #include<IOSTREAM> using namespace std; typedef struct Single_link { int data; struct Single_link *next; }node; //单链表的创建 node *Create() { node *head,*p,*s; int x,cycle=1; head=(node *)malloc(sizeof(node)); p

C:TLV消息编码及常用操作

/* 1.TLV简介: 在通信系统中,两个设备之前必然存在消息交互,消息的格式也存在各种编码类型, 本文仅描述TLV编码的消息格式.Type-length-value(TLV)格式中T.L的长度固定, 通常为1-8个4个字节,V的长度不固定,由L的值表示,V的内容也可以嵌套子TLV格式. 举例:假设消息按大端模式存放,T占4个字节,L占2个字节,下面的消息: unsigned char pMsg[] = {0x09, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01,0x01

C:二维数组常用操作

/* 说明:程序实现二维数组中插入列.插入行.交换两个指定位置的元素,并输出指定 位置元素的变化轨迹 作者:socrates 日期:2014-08-17 */ #include "stdafx.h" #include <stdlib.h> #include <assert.h> /*二维数组最大行数和列数*/ #define MAX_ROW_NUM (9) #define MAX_COL_NUM (9) /*二维数组中各元素位置信息*/ typedef stru

二叉树的性质和常用操作代码集合

二叉树的性质和常用操作代码集合 性质: 二叉树的性质和常用代码操作集合 性质1:在二叉树的第i层上至多有2^i-1个结点 性质2:深度为k的二叉树至多有2^k - 1个结点 性质3:对任意一棵二叉树T,若终端结点数为n0,而其度数为2的结点数为n2,则n0 = n2 + 1 满二叉树:深度为k且有2^-1个结点的树 完全二叉树:深度为k,结点数为n的二叉树,如果其结点1~n的位置序号分别与等高的满二叉树的结 点1~n的位置序号一一对应,则为完全二叉树. 性质4:具有n的结点的完全二叉树深度为lo

5种redis常用操作(数据类型+键值+服务+安全)

[toc] 5种redis常用数据类型操作 一.Redis常用操作 (string, list) 1.1 如果一个key设置两个不同的值,第二个值会覆盖第一个值. [[email protected] ~]# cd /usr/local/src/redis-4.0.9 [[email protected] redis-4.0.9]# redis-cli 127.0.0.1:6379> set key1 xavi OK 127.0.0.1:6379> set key2 xavilinux OK

1 数据结构(13)_二叉树的概念及常用操作实现

1. 树到二叉树的转换 思考:通用树结构的实现太过复杂(树中每个结点都可以有任意多的孩子,具有多种形态),工程中很少会用到如此复杂的树是否可以简化呢?思路:减少树结点中孩子的数量.但这样树是否还能通用呢? 1.1.树的两种表示法 双亲孩子表示法:孩子兄弟表示法:孩子兄弟表示法的特点:1.能够表示任意的树形结构2.每个结点包含一个数据成员和两个指针成员3.孩子结点指针和兄弟结点指针构成"树杈" 2.2.二叉树 二叉树是由n(n>=0)个节点组成的有限集合,该集合或者为空,或者是由一

redis常用操作、 redis操作键值、 redis安全设置

一:redis常用操作 Redis常用操作?(string, list)set key1 aminglinuxget key1set key1 aming//第二次赋值会覆盖setnx key2 aaa //返回1 如果key2不存在直接创建keysetnx key2 bbb //返回0,如果key2存在,返回0setex key3 10 1 //给key3设置过期时间为10s,值为1,若key已经存在,会覆盖新的值mset k1 1 k2 a k3 cmget k1 k3 k2lpush li

Python 字典的特点和常用操作

一.字典帮助文档 >>> dir(dict) ['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt