单链表实现
来源:互联网 发布:养生网站源码带手机站 编辑:程序博客网 时间:2024/06/08 15:01
目录
线性表是数据结构的第一章,而考研和找工作都喜欢考察这方面的内容,因此,我就用C++实现了单链表,以及一些常见的算法题。
本文的具体内容包括:
- 单链表的基本操作
- 反向输出单链表
- 找到两个单链表的第一个公共结点
- 对单链表进行排序
- 将两个有序的链表合在一起,使之仍然有序
单链表的基本操作
不多说,直接上代码(注意基本操作中参数L的不同):
///初始化一个单链表,申请头结点void InitList(LinkList *L){ *L = new LNode; if(*L==NULL){ cout<<"new error"<<endl; return; } (*L)->next = NULL;}///释放头结点,将其设为nullvoid DestroyList(LinkList *L){ LinkList t ; while((*L)!=NULL){ t = (*L)->next; delete (*L); (*L) = t; }}///释放除头结点以外的所有空间void ClearList(LinkList L){ LinkList t,q=L; L = L->next; while(L!=NULL){ t = L->next; delete L; L = t; } q->next = NULL;}///获取链表的长度int Length(LinkList L){ if(L == NULL) return -1; int cnt = 0; L = L->next; while(L!=NULL){ ++cnt; L=L->next; } return cnt;}///返回链表L中第1个与e相等的元素的位置int locateElem(LinkList L,int e){ if(L==NULL) return -1; int index = 0; L = L->next; while(L!=NULL){ if(L->data==e){ return index; } ++index; L = L->next; } return -1;}///获取链表第i个元素的值bool getElem(LinkList L,int i,LNode &e){ if(L==NULL or i<0) return false; int j = 0; L = L->next; while(L!=NULL){ if(j==i){ e.data=L->data; e.next=L->next; return true; } ++j; L = L->next; } return false;}///在L中第i个位置插入结点ebool ListInsert(LinkList L,int i,LNode e){ if(L==NULL) return false; LinkList p; p = L; L = L->next; int j = 0; while(p!=NULL){ if(j==i){ LinkList t; t = new LNode; t->data = e.data; t->next = e.next; p->next = t; t->next = L; return true; } p = L; L = L->next; ++j; } return false;}///删除第i个元素,并返回该结点bool ListDelete(LinkList L,int i,LNode &e){ if(L==NULL) return false; LinkList p; int j = 0; p = L; L = L->next; while(L!=NULL){ if(i==j){ e.data = L->data; e.next = L->next; p->next = L->next; delete L; return true; } p = p->next; L = L->next; ++j; } return false;}///打印单链表Lvoid PrintList(LinkList L){ if(L==NULL) return; L = L->next; while(L!=NULL){ cout<<L->data<<' '; L = L->next; } cout<<" end"<<endl;}
测试代码:
LinkList L; InitList(&L); cout<<"the address of the head node is "<<L<<endl; LNode e; e.data = 124; e.next = NULL; ListInsert(L,0,e); e.data = 132; ListInsert(L,0,e); e.data = 123; ListInsert(L,0,e); PrintList(L); cout<<"the length of L is "<<Length(L)<<endl; cout<<"the location of 132 is "<<locateElem(L,132)<<endl; if(getElem(L,1,e)){ cout<<"the value of location 1 is "<<e.data<<endl; } if(ListDelete(L,1,e)) cout<<"the value of deleted element is "<<e.data<<endl; else cout<<"delete failed"<<endl; ClearList(L); cout<<L<<endl; DestroyList(&L); cout<<L<<endl;
运行结果:
反向输出单链表
///从尾到头反向输出单链表L///思路:反向输出很容易就想到栈,///然后递归的本质就是栈,因此可以用///递归来实现,先一层层递归到链表尾部,///当指针为NULL时,返回,返回时输出当前节点的值void PrintListByReverse(LinkList L){ if(L==NULL) return; PrintListByReverse(L->next); cout<<L->data<<' ';}
测试代码:
LinkList L; InitList(&L); LNode e; e.data = 124; e.next = NULL; ListInsert(L,0,e); e.data = 132; ListInsert(L,0,e); e.data = 123; ListInsert(L,0,e); e.data = 88; ListInsert(L,0,e); e.data = 14; ListInsert(L,0,e); e.data = 26; ListInsert(L,0,e); cout<<"the origin linklist is:"<<endl; PrintList(L); cout<<"print list in reverse:"<<endl; PrintListByReverse(L->next); cout<<"end"<<endl;
运行结果:
求两个单链表的公共结点
///找到两个链表的第一个公共结点/**< 思路:若两个单链表有公共结点,那么他们的逻辑结构肯定是Y形而不是X形(因为节点的next域只有一个),因此,可以先计算两个链表的长度,然后先让较长的先移动d(他们的长度差)个节点这样他们就会同时到达公共结点,只需比较两个指针就可以了 */bool FindCommonNode(LinkList La,LinkList Lb,LNode &e){ if(La==NULL || Lb==NULL) return false; int la,lb;///La/Lb 的长度 la = Length(La); lb = Length(Lb); int d = la-lb; int i = 0; La = La->next; Lb = Lb->next; if(d>0){ while(La!=NULL){ if(i==d){ break; } ++i; La = La->next; } } else{ d=-d; while(Lb!=NULL){ if(i==d){ break; } ++i; Lb = Lb->next; } } while(La!=NULL && Lb!=NULL){ if(La == Lb){ e.data = La->data; e.next = La->next; return true; } La = La->next; Lb = Lb->next; } return false;}
测试代码:
LinkList L; InitList(&L); LNode e; e.data = 124; e.next = NULL; ListInsert(L,0,e); e.data = 132; ListInsert(L,0,e); LinkList myList; InitList(&myList); e.data = 83; ListInsert(myList,0,e); e.data = 19; ListInsert(myList,0,e); e.data = 46; ListInsert(myList,0,e); ConcatList(myList,L); cout<<"list 1 is:"<<endl; PrintList(myList); LinkList hisList; InitList(&hisList); e.data = 547; ListInsert(hisList,0,e); e.data = 78; ListInsert(hisList,0,e); ConcatList(hisList,L); cout<<"list 2 is:"<<endl; PrintList(hisList); if(FindCommonNode(myList,hisList,e)) cout<<"the first common node is "<<e.data<<endl;
运行结果:
单链表排序
///对单链表进行排序/**< 可使用插入排序,每次从后面选择一个结点,在前面有序的序列选择一个合适的位置插入 */void SortList(LinkList L){ if(L==NULL) return; LinkList q,r,s,x; r = L; x = L; L=L->next; bool flag; while(L!=NULL){ ///在前面找到合适的位置插入 s = r; q = r->next; flag = false; while(q!=NULL && q!=L){ ///找到第一个比当前结点大的结点 if(q->data > L->data){ flag = true; x->next = L->next; L->next = q; s->next = L; //PrintList(r); break; } s = s->next; q = q->next; } if(flag!= true) x=x->next; L=x->next; }}
测试代码:
LinkList L; InitList(&L); LNode e; e.data = 124; e.next = NULL; ListInsert(L,0,e); e.data = 132; ListInsert(L,0,e); LinkList myList; InitList(&myList); e.data = 83; ListInsert(myList,0,e); e.data = 19; ListInsert(myList,0,e); e.data = 46; ListInsert(myList,0,e); ConcatList(myList,L); cout<<"before sort:"<<endl; PrintList(myList); SortList(myList); cout<<"after sort:"<<endl; PrintList(myList);
运行结果:
合并有序单链表
///合并有序单链表La、Lb,放到La里面去,并且合并后的链表仍然有序void MergeList(LinkList La,LinkList Lb){ LinkList pa = La->next,pb = Lb->next,t; LNode *r; La->next = NULL; ///La 作为结果链表的指针 t = La; while(pa != NULL && pb != NULL){ if(pa->data > pb->data){ r = pb->next; ///r 暂存pb的后继结点 ///在La插入 pb->next = La->next; La->next = pb; ///恢复pb为下一个待比较结点 pb = r; La = La->next; } else{ r = pa->next; ///r 暂存pb的后继结点 ///在La插入 pa->next = La->next; La->next = pa; ///恢复pb为下一个待比较结点 pa = r; La = La->next; } //PrintList(t); } if(pa!=NULL) La->next = pa; if(pb!=NULL) La->next = pb; delete Lb;}
测试代码:
LNode e; LinkList List1; InitList(&List1); e.data = 24; ListInsert(List1,0,e); e.data = 68; ListInsert(List1,0,e); e.data = 35; ListInsert(List1,0,e); e.data = 123; ListInsert(List1,0,e); e.data = 77; ListInsert(List1,0,e); e.data = 15; ListInsert(List1,0,e); SortList(List1); LinkList List2; InitList(&List2); e.data = 23; ListInsert(List2,0,e); e.data = 46; ListInsert(List2,0,e); e.data = 98; ListInsert(List2,0,e); e.data = 143; ListInsert(List2,0,e); e.data = 18; ListInsert(List2,0,e); e.data = 85; ListInsert(List2,0,e); SortList(List2); cout<<"list 1 is :"<<endl; PrintList(List1); cout<<"list 2 is :"<<endl; PrintList(List2); MergeList(List1,List2); cout<<"after merge:"<<endl; PrintList(List1);
运行结果:
总结
虽然说单链表逻辑比较简单,但是涉及指针操作,很容易出错,我建议在纸上画图来编写代码,这样思路比较清晰。
阅读全文
0 0
- 单链表实现
- 单链表实现
- 单链表实现!
- 单链表实现
- 单链表实现
- 单链表实现
- 单链表实现
- 单链表实现
- 单链表实现
- 单链表实现
- 单链表实现
- 【算法数据结构Java实现】Java实现单链表
- 单链表的基础实现
- 数据结构-单链表的实现
- c#实现单链表
- 单链表(C#)实现
- 循环单链表的实现
- 数据结构---单链表实现(源码)
- 关于光耦的电流传输比
- draft js 服务端node 执行
- MVC , MVP , MVVM的图解
- 【知乎整理】云计算和虚拟机(VMWare)有什么区别?
- JavaWeb学习之JSP九大内置对象
- 单链表实现
- 设计模式之简单工厂模式(以计算器为例)
- Android M 新的运行时权限
- 分区表不建议创建主键的原因
- 新安装的 eclipse 导入过去的项目,出现乱码的解决方法
- linux下vi命令大全
- CROS代理跨域
- flask
- hbuilder项目总结:下载附件判断是否打开并在本地管理已下载附件