Day13 设在一个带头节点的单链表中所有元素的节点的数据值无序,试编写一个函数,删除表中所有介于给定两个数值之间的元素
思想:
1、算法思路
进行删除指定条件下的节点
先查找该指定节点
删除指定节点
2、查找指定节点
以条件区间【min,max】为匹配数值进行遍历链表查找,
3、删除元素
步骤主要是:
设置一个前驱指针进行next指向当前删除指针的next
free释放当前删除指针的内存
为p重新赋值

//核心代码
void Delete(Linklist&L,int min,int max)
LNode*pre=L;
*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同时向后移一位
pre=p;
p=p->next;
}
Day14 给定两个单链表 编写 找出两个单链表的公共结点
1、题目分析!!!!!!!重要
首先是看到这个题目后,大脑中构思的有公共节点的两个单链表的连接情况,无非是下面这两种:
第一种:

第二种:

下面对这两种情况进行分析:
首先是第一种情况,由于单链表的next指针域只有一个,因此只能指向一个节点第一种情况明显是违背了,
因此第一种情况是错误的
第二种情况分析:
第二种情况建立的依据便是对公共节点的进行设置,可以得到,如果单链表在遍历的过程中,找到了一个公共节点,那么剩余的节点都是公共节点。
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;//无公共节点
}
分析:时间复杂度O(LA*LB)
如何优化:不利用双重循环 时间复杂度是线性的方法
如何寻找公共节点
如何判断两条链表存在同样结点
思路:1.如何寻找公共结点 若可以同时到达表尾 则一定是公共节点
2.如何同时到达表尾(1)若两条链表长度相同那必定可以找到
(2)不相等 如何同时到达表尾
(3)先K=length A-length B 先让P指针移动k次 然后再p q同步向后移动 就可以同时到达表尾

//优化单链表求公共节点
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;//以上都没有找到
}
时间复杂度:O(lenA+lenB )
Day 15
将带头结点的单链表A分解为两个带头结点的单链表A与B,使得A表中含有原表中序号为奇数的元素,而B表中含有原表中序号为偶数的元素且保持相对顺序不变
分析:
顺序不变 不断使用尾插法 依次生成链表AB
生成一个i%2=0/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 Creat(Linklist&A){
int i=0;//结点序号初始化
//开辟新的链表空间
B=(LNode*)malloc(Sizeof(LNode));
LNode*p=A->next;
A->next=NULL;
LNode*ra;
LNode*rb=B;//初始化指针
}
//核心代码 偶数插b 奇数插a
while(p!=NULL){
if(i%2==0){
rb->next=p
rb=p;
}else{
ra->next=p;
ra=p;
}
}
//尾插法重点:
//必须要设置最后节点为null指向
ra->next = null;
rb->next = null;
return B;}
dat 16
设C为{a1,b1,a2,b2…an,bn}为线性表,采用带头节点的hc单链表存放,设计一个就地算法,将其线性表拆分为两个线性表,使得A={a1,a2,a3…an},B={bn,bn-1,…b2,b1}

思想:遍历c链表 将第一个结点尾插在A中 第二个头插在B中 下一个尾插A以此类推直至拆分A B
//顺序拆分单链表,A顺序尾插法,B顺序头插法
Linklist Create_Linklist(Linklist &hc){
//初始化节点
LNode * r;
LNode * p = hc->next;
//链表初始化
A = (Linklist)malloc(sizeof(LNode));
B = (Linklist)malloc(sizeof(LNode));
A->next = null;
LNode * ra = A;
B->next = null;
LNode * rb = B;
//核心操作代码
while(p!= null){
//按照第二种方式,从第一个元素开始进行拆分,
//第一个是a1,因此采用尾插法进行插入A链表
ra->next = p;
ra = p;//尾插法
p = p->next;//向后移动p
if(p != null){//p后面还有元素
//这里进行头插法进行操作
/**
* 记忆口诀:
* 头插法防止断链
* 尾插法要留尾部指针为null
*/
r = p->next;//保存防止断链
p->next = rb->next;//头插法建立单链表的过程操作
rb->next = p;
p = r;
}
}
return A;
return B;
}
拆分单链表:奇偶元素分离与公共节点查找

被折叠的 条评论
为什么被折叠?



