题目01
题目描述:
设在一个带头节点的单链表中所有元素的节点的数据值无序,试编写一个函数,删除表中所有介于给定两个数值之间的元素
1、算法思路
2、查找指定节点
以条件区间【min,max】为匹配数值进行遍历链表查找,
3、删除元素
步骤主要是:
其实现代码如下:
//删除单链表中指定区间【min,max】的数据
//这里的L因为要进行删除操作,必须添加&符号,并设置为Elemtype类型
void Delete_RangeOfNode(Linklist &L,ElemType min,ElemType max){
//初始化指针
LNode * pre = L;//头节点赋值
LNode * p = L->next;
//遍历链表核心代码
while(p != Null){
//查找数值
if(p->data > min && p->data < max){
pre->next = p->next;//进行范围节点删除
free(p);//释放内存
p = pre->next;//为p重新初始化数值
}else{//若没有找到
//前驱和后继都往前移动
pre = p;
p = p->next;
}
}
}
题目02
题目描述:
给定两个单链表,编写算法找到两个单链表的公共节点
1、题目分析!!!!!!!重要
第二种情况分析:
2、算法思路分析
对于找公共节点,这里首先想到的便是遍历链表进行查找,不论有多少的节点都要进行遍历,因此遍历法也被称为暴力法
1、暴力法实现思路:
2、算法图解如下:
因此其暴力法的核心便是两个循环的遍历链表,若其中的p与q对应的指针域的数据不相等,那么寻找失败
其代码实现如下:
//暴力法寻找两个单链表的公共节点
LNode * GetCommonNode(Linklist &A,Linklist &B){
//初始化指针
LNode * p = A->next;
LNode * q = B->next;
//使用双循环
while(p != null){//外循环作为比较第一趟的结束后移
while(q != null){
if(p == q){//找到了公共节点
return p;
}else{//没有找到
q = q->next;
}
//B链表全部走完一糖都没有找到公共节点
p = p->next;//p后移
q = B->next;//重置q的指针位置
}
}
//以上的全部都没有找到公共节点
return null;//无公共节点
}
代码分析:
1、核心操作代码:
//使用双循环
while(p != null){//外循环作为比较第一趟的结束后移
while(q != null){
if(p == q){//找到了公共节点
return p;
}else{//没有找到
q = q->next;
}
//B链表全部走完一糖都没有找到公共节点
p = p->next;//p后移
q = B->next;//重置q的指针位置
}
}
q指针走完一趟处理:
q = q->next;
p指针操作
p = p->next;//p后移
q = B->next;//重置q的指针位置
重点:!!!结合上面的查找公共节点的代码进行时间复杂度分析,这里我们使用了双循环,因此其时间复杂度0(A链表长度*B链表长度)。这样的时间复杂度是非常大的,因此我们必须要对其进行优化代码。
下面是对当前题目的算法优化思路以及代码实现
寻找优化之路
结合题目要求对其进行反推分析:
这里我们对其长链表进行长度限制,以与短链表的差距节点为起始节点进行和设计。
其实现的代码如下:
//优化单链表求公共节点
LNode * GetCommonNodeByGoodNess(Linklist &A,Linklist &B){
LNode * p ;
LNode * q;
//求出链表的长度
int k = 0;//定义差值
int A_length = GetLength(A);
int B_length = GetLength(B);
//对长度比大小
if(A_length > B_length){
k = A_length - B_length;
p = A->next;//初始化指针
q = B->next;
}else{
//B时长链
k = B_length - A_length;
p = B->next;
q = A->next;//p要保证始终指向长链表
}
//对长链表的起始节点的位置进行调正
while(k--){
p = p->next;
}
//核心代码进行比较
while(p != null){
if(p == q){
return p;
}else{
p = p->next;
q = q->next;//当前的不是最后的节点,进行后移
}
}
return null;//以上都没有找到
}
结合以上的代码进行时间复杂度分析,得到的时间复杂度为0(A的长度+B的长度),优化代码成功!!!!!!!!!!!!
核心代码:
//核心代码进行比较
while(p != null){
if(p == q){
return p;
}else{
p = p->next;
q = q->next;//当前的不是最后的节点,进行后移
}
}
调整代码:
int k = 0;//定义差值
int A_length = GetLength(A);
int B_length = GetLength(B);
//对长度比大小
if(A_length > B_length){
k = A_length - B_length;
p = A->next;//初始化指针
q = B->next;
}else{
//B时长链
k = B_length - A_length;
p = B->next;
q = A->next;//p要保证始终指向长链表
}
//对长链表的起始节点的位置进行调正
while(k--){
p = p->next;
}
题目03
将一个带有头节点的单链表A分解为两个带头节点的单链表A和B,使得A表中原始的奇数序号数,B为偶数序号是数,相对位置不变
1、算法设计思路图解分析:
因此这里 实现过程与尾插法建立单链表类似,因此我们便有了代码设计的思路-------------尾插法
下面时一段尾插法建立单链表的代码:
//尾插法建立单链表
Listlink List_TailInsert(Linklist &L){
LNode * s;
L = (Linklist)malloc(sizeof(LNode));
LNode * r = L;//指向根节点
int x;
scanf("%d",&x);//赋值
while(x != -1){
//核心代码
s = (LNode*)malloc(sizeof(LNode));
s->data = x;
r->next = s;
r = s;
}
//在最后添加后需要对为节点设置为null
r->next = null;//设置r的下一个为null
}
下面让我们类似上面这一段代码编写解题代码:
//分割单链表
Linklist Create(Linklist &A){
int i = 0;//节点的序号初始化
//开辟新的链表空间
B = (Linklist)malloc(sizeof(LNode));
LNode * p = A->next;
A->next = NULL;
LNode * ra;
LNode * rb = B;//初始化指针
while(p != null){
if(i % 2 == 0){//偶数
rb->next = p;//尾插法建立单链表精髓代码
rb = p;
}else{//若是奇数序列
ra->next = p;
ra = p;
}
//进行遍历主链表开启下一轮循环
p = p->next;
i++;
}
//尾插法重点:
//必须要设置最后节点为null指向
ra->next = null;
rb->next = null;
return B;
}
解决!
注:
个人代码问题或需要程序编写辅导服务等问题请加闲鱼【代码无bug】
或点击下面链接跳转闲鱼进行咨询
闲鱼链接