数据结构代码题---寻找指定结点

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);
} 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XUN~MLF

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值