数据结构代码题总结
题目01
已知两个链表A和B分别表示两个集合,其元素递增有序排列,编制函数求A和B的交集,并存放在A链表中
题目分析:
- 求A和B的交集,与求A和B的公共元素不同
- 并存在在A链表中,-----代表着不可以再申请一个链表的存储空间
- 与不破坏A和B的结构节点不相同,这里不可以再申请一个新的链表空间。
- 存放在A链表中表示只可以在A链表上修改
算法思路图解
结合以上的算法图解,对其算法思路进行概述:
- 设置两个扫描指针p和q,进行对A和B链表的扫描进行操作,同时对其进行p和q所指向节点的数据进行比较
- 较小的数据进行后移,
- 若数据域相等时,这时进行标记节点标记删除节点,并对节点进行删除,释放空间
- 若遍历到表尾后,发现A或者B有剩余,因为已经有一个链表遍历完成,所以不会再存在相同的指针节点。直接释放空间就可以
这里强调下删除一个节点的步骤:
1、先使用一个标记节点u标记删除节点
2、将带删除节点指针后移
3、 free释放空间
下面是代码实现的核心代码:
//核心代码
while(p != null && q != null){
//进行比较
if(p->data < q->data){//不是交集的是直接释放删除
u = p;
p = p->next;
free(u);
}else if(p->data > q->data){//删除不必要的交集节点
u = p;
p = p->next;
free(u);
}else{//现在找到了相等的节点了,进行尾插法进行插入到A链表
r->next = p;
r = p;//保存A,释放B
u= q;//考虑到资源的利用问题进行多余的节点删除
q = q->next;
free(u);
}
}
//跳出循环说明A或者B出现一条链表遍历完毕,另一条未遍历完毕
while(p != null){//A有剩余
u = p;
p =p->next;
free(u);
}
while(q != null){//B有剩余
u = q;
q = q->next;
free(u);
}
//尾插法必须设置尾指针
r->next = null;
free(B);//完全释放B节点
完整代码如下:
//找到链表的交集
Linklist Common_List(Linklist &A,Linklist &B){
//初始化指针
LNode * p = A->next;
LNode * q = B->next;
LNode * u;//作为标记指针
A->next = null;//尾插法使用标准开端
//设置一个尾插法的操作指针
LNode * r = A;
//核心代码
while(p != null && q != null){
//进行比较
if(p->data < q->data){//不是交集的是直接释放删除
u = p;
p = p->next;
free(u);
}else if(p->data > q->data){//删除不必要的交集节点
u = p;
p = p->next;
free(u);
}else{//现在找到了相等的节点了,进行尾插法进行插入到A链表
r->next = p;
r = p;//保存A,释放B
u= q;//考虑到资源的利用问题进行多余的节点删除
q = q->next;
free(u);
}
}
//跳出循环说明A或者B出现一条链表遍历完毕,另一条未遍历完毕
while(p != null){//A有剩余
u = p;
p =p->next;
free(u);
}
while(q != null){//B有剩余
u = q;
q = q->next;
free(u);
}
//尾插法必须设置尾指针
r->next = null;
free(B);//完全释放B节点
return A;//返回A的操作节点
}
题目02
两个整数序列A = a1,a2,a3…am和B=b1,b2,b3…bn已经存入两个单链表中,设计一个算法,判断序列B是否是A的连续子序列
题目分析:
连续子序列-----代表要在A链表中找到一段连续的序与A进行对应。
关键在于如何在A中寻找B的连续子序列
答案是在我们无法首先得到最优化的解答时,暴力法无疑是能够最快拿到代码题分数的一个性价比极高的方法,相比于写不出来的代码题答案,在考试时使用暴力法写出来解答代码,虽然时间复杂度有时候会高点,但是基本的分数时很有保障的。
下面主要来讲解下暴力法解决连续子序列的问题,先看图
算法实现思路如下:
- 暴力法对p和q的数据域进行比较,
- 若数据域不相等,
- 那么p指针并在上次结束的位置进行向后移动
- q指针则是在起始位置进行移动
- 若相等,
- 那么p和q指针同时向后移动
- 判断结果处理:
- (1)若p在q之前先遍历结束,那么p中绝对不会存在B的连续子序列,
- (2)若q先遍历完,说明找到了子序列,因此返回true
其实现的核心代码如下:
while(p != null && q != null){
if(p->data != q->data){
pre = pre->next;//找到之前pre节点的下一个节点
p = pre;//设置p
q = B->next;//q从头开始
}else{
p = p->next;
q = q->next;//相等同时往后移
}
}
//跳出循环
if(q == null){//以q为主进行比较判断
return true;
}
return false;
完整代码如下:
//查找连续组序列
boolean Find_SonLink(Linklist A,Linklist B){
LNode * p = A->next;
LNode * q = B->next;
LNode * pre = p;//定义一个pre指针
while(p != null && q != null){
if(p->data != q->data){
pre = pre->next;//找到之前pre节点的下一个节点
p = pre;//设置p
q = B->next;//q从头开始
}else{
p = p->next;
q = q->next;//相等同时往后移
}
}
//跳出循环
if(q == null){//以q为主进行比较判断
return true;
}
return false;
}
题目03
设计一个算法,判断带头结点的循环双链表是否对称
题目解析
什么是循环双链表对称??????
请先看下图
循环双链表对称的定义:
- 首尾的数据域在前进移动的过程中始终相等。
- 偶数节点的循环双链表,在p和q遍历的过程中,最终节点是(p==q)
- 奇数节点的结束条件是(q的next指向p)p和q相邻。
其实现代码如下:
while(p != q && q->next != p){
//偶数节点出循环 //奇数节点出循环
if(p->data == q->data){
p = p->next;
q = q->prior;
}else{
return false;
}
}
return true;
完整代码如下:
//双链表结构体
typedef struct DLNode{
ElemType data;
struct DLNode * prior,*next;
}DLNode;
//是否对称
boolean Symmetry_link(DLinklist L){
DLNode *p = L->next;
DLNode *q =L->prior;
while(p != q && q->next != p){
//偶数节点出循环 //奇数节点出循环
if(p->data == q->data){
p = p->next;
q = q->prior;
}else{
return false;
}
}
return true;
}
题目04
两个循环链表h1和h2,编写一个函数将h2加入到h1之后,保持链表循环的形式
图解:
实现代码如下:
Linklist conn_link(Linklist &h1,Linklist &h2){
LNode *p = h1;
LNode * q = h2;
//调整到表尾
while(p!= h1){//作为链表尾部判断
p = p->next;
}
while(q!= h2){//作为循环链表尾部判断
q = q->next;
}
p->next = h2->next;//由于h2为头结点,在进行循环链表合并时,该节点不存储数据,因此为保证连续性,将h1链表的尾部的next指向h2的第一个数据节点。
free(h2);//该步骤可释放也可不释放,理解算法思想即可
q->next = h1;//进行尾部首部链接,保证为一个循环链表
return h1;//返回循环链表
}
注:
个人代码问题或需要程序编写辅导服务等问题请加闲鱼【代码无bug】
或点击下面链接跳转闲鱼进行咨询