1、给定两个单链表,找出两个链表的公共结点
// 方法一 :双循环,时间复杂度高
// 单链表的定义
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*算法思想:暴力解法 ,通过循环,指针p用于遍历A链表,指针q用于遍历B链表,
p先指向第一个结点,然后遍历B链表,让B中的每一个节点和p比较,找到相同结点则直接返回,
如果没有找到,p指向下一个结点,q返回第一个结点,知道p指向空循环结束
*/
LinkList Search_common(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; //
}
}
// 一轮循环没有找到相同结点
p = p->next;
q = B->next;
}
}
// 方法二:是否同时到达表尾
/*算法思想:让两条链表同时到达表尾,如果有公共结点,那么p,q可以同时到达表尾,没有公共结点的话,p,q不能同时到达表尾
如果A,B链表等长,那么就同时向后移动,如果A,B链表不等长,那么就先让长的链表先移动K个单位,两条链表等长以后再同时向后移动*/
// 单链表的定义
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*求表长*/
int ListLen(LinkList L){
LNode *p = L->next;
int len = 0;
while(p!=NULL){
len++;
p = p->next;
}
return len;
}
LinkList Search_common(LinkList A,LinkList B){
LNode *p; // 指向更长的链表
LNode *q; // 指向更短的链表
int k;
int lenA = ListLen(A);
int lenB = ListLen(B);
if(lenA>lenB){
k = lenA-lenB; // 求出两个链表长度差
p = A->next;
q = B->next;
}else{
k = lenB-lenA; // 求出两个链表长度差
p = B->next;
q = A->next;
}
while(k--){
p = p->next; // 长的链表先向前移动k位,然后两条链表同时移动
}
while(p!=NULL){
if(p == q){ // 找到公共结点
return p;
}else{ // 没有找到公共结点,p , q同时向后移动
p = p->next;
q = q->next;
}
}
return NULL;
}
2、假定采用带头结点的单链表保存单词,当两个单词有相同的后缀时,可以共享相同的后缀空间,例如 loading, being,请设置算法找到两个链表共同后缀的起始地址
// 单链表的定义
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*求表长*/
int ListLen(LinkList L){
LNode *p = L->next;
int len = 0;
while(p!=NULL){
len++;
p = p->next;
}
return len;
}
LinkList Search_common(LinkList A,LinkList B){
LNode *p; // 指向更长的链表
LNode *q; // 指向更短的链表
int lenA = ListLen(A);
int lenB = ListLen(B);
for(p = A->next;lenA>lenB;lenA--){ // A更长,p向后移
p = p->next;
}
for(q = B->next;lenB>lenA;lenB--){ // B更长,q向后移
q = q->next;
}
while(p!=NULL&&p!=q){ // 没有公共后缀
p = p->next;
q = q->next;
}
if(p==NULL){
return NULL;
} else{
return p;
}
}
}
3、寻找倒数第k个结点 双指针,间隔一定,同步后移
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*算法思想:先将p移动到第k个位置,p,q一起后移,直到p指到表尾结点,则q指向倒数第k个结点 */
int Search_K(LinkList L,int k){
int count = 0;
LNode *p = L->next,*q = L->next;
while(p!=NULL){
if(count<k){
count++; // 计数, 如果count<k 则只移动p;
}else{
q = q->next; // 之后让p,q同时移动
}
p = p->next;
}
if(count<k){
return 0;
}else{
printf("%d",q->data);
return 1;
}
}
4、寻找相同子序列
两个整数子序列A = a1,a2……an B= b1,b2,……bn,存放到两个单链表中,判断序列B是否为A的连续子序列
// 单链表的定义
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*算法思想:暴力法:类似字符串的模式匹配,依次遍历A和B链表,如果data值相同,同时后移,如果不相同
A返回开始比较结点的后继结点,B则从头开始
*/
bool Pattern(LinkList A,LinkList B){
LNode *p = A->next;
LNode *q = B->next;
LNode *pre = p;
while(p!=NULL&&q!=NULL){
if(p->data == q->data){ // 结点值相同,两个结点同时向后移
p = p->next;
q = q->next;
}else{
pre = pre->next; //
p = pre; // A返回开始比较结点的后继结点
q = B->next; // B则从头开始
}
}
if(q == NULL){ // B中没有元素了,说明B是A的自序列
return true;
}else{
return false;
}
}
判断带头结点的循环双链表是否对称 (元素值)
// 双链表的定义
typedef struct DNode{
ElemType data;
struct DNode *prior,*next;
}DNode,*DLinkList;
/*算法思想:让p结点从左往右移动,q结点从右往左移动,直到他们指向同一个结点
当循环双链表中结点个数为奇数个时(p=q),当结点为偶数个时(p->next = q,q->prior = p)
*/
int Symmetry(DLinkList &A){
DNode *p = A->next,*q = A->prior;
while(p!=q && q->prior = p){
if(p->data == q->next){ // 元素值相同,指针同时移动
p = p->next;
q = q->prior;
}
else{ // 只要有一个元素不相等就不对称
return 0;
}
}
return 1;
}
有两个循环单链表,头指针分别为 h1,h2,将其合并
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*算法思想:找到h1的表尾结点p,找到h2的表尾结点q,将p指向h2,q指向h1,构成一整条循环单链表*/
LinkList Link(LinkList &h1,LinkList &h2){
LNode *p,*q;
p = h1;
q = h2;
while(p->next!=NULL){ // 寻找h1的表尾结点
p = p->next;
}
while(q->next!=NULL){ // 寻找h2的表尾结点
q = q->next;
}
p->next = h2;
q->next = h1;
return h1;
}
3、反复找出循环单链表中结点值最小的结点并输出,然后将结点删除,直到链表为空,再删除表头结点
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
/*算法思想:反复找出当前的最小值结点,并删除,直到链表为空,释放头结点L*/
void Del_all(LinkList &L){
LNode *p,*pre,*minp,*minpre;
while(L->next!=L){
p = L->next;
pre = L;
minp = p;
minpre = pre;
while(p!=L){
if(p->data < minp->data){ // 找最小值结点
minp = p;
minpre = pre;
}
pre = p;
p = p->next;
}
printf("%d",minp->data);
minpre->next = minp->next;
free(minp);
}
free(L);
}