算法之路(C++)

一,链表

1,两个单链表合并,取相同数据问题

题目:设A、B是两个单链表(带头结点),其中元素递增有序,设计一个算法从A、B中的公共元素产生单链表C,要求不破坏A、B节点
分析:
要求不破坏A、B节点,故我们需要重新创建分配节点空间,来进行连接。为寻找公共元素,每遍历A中的一个元素,都去与B中元素一一比较,同则取值给另一空间节点,连接到C上。时间复杂度为O(n^2)。
因为这两个链表是递增有序的,那么我们可以设置两个指针同步比较,相同则加入c,不同小的那个往后移,直至到链表末尾这样的时间复杂度为O(n).

代码:

#include <stdlib.h>
#include <stdio.h>
//单向链表,如果是双向链表,需要加个head
struct Link {
	int data;
	struct Link *next;
};
//方法一:不要用这种,简单初级,不考虑时间复杂度
void linkCommon(Link *a, Link *b, Link *c ) {
	struct Link *lc = c,*la=a->next,*lb=b->next,*rc=lc;
	while (la) {
		while (lb) {
			if (la->data==lb->data) {//如果是公共元素
				struct Link *p = (struct Link*)malloc(sizeof(struct Link));
				p->data = la->data;
				rc->next = p;//采用尾插法
				rc = p;
				break;
			}
			lb = lb->next;
		}
		la = la->next;
		lb = b->next;
	}
	rc->next = NULL;//最后一个节点指针需要指向NULL。
}
//方法二
//a,b是两个已知链表,c是载体,存放相同数据的链表
void listCommon(Link *a,Link *b,Link *c) {
	struct Link *rc = c, *la = a->next, *lb = b->next;
	while (la&&lb) {
		if (la->data==lb->data) {
			struct Link *p = (struct Link*)malloc(sizeof(struct Link));
			p->data = la->data;
			p->next = NULL;
			rc->next = p;
			rc = p;
			la = la->next;
			lb = lb->next;
		}
		else {
			la->data < lb->data ? la = la->next : lb = lb->next;
		}
	}
	rc->next = NULL;
}
int main() {
	struct Link *a, *b;
	Link *createLink();
	void printfNowLink(Link *);
	a = createLink();
	b = createLink();
	struct Link *c = (struct Link*)malloc(sizeof(struct Link));
	c->next = NULL;
	//linkCommon(a,b,c);
	listCommon(a,b,c);
	printfNowLink(c);
	return 0;
}

2,两个单链表合并为一个单链表问题

目的:掌握单链表的应用和算法设计
题目:L1 =(x1, x2, …, xn ),L2 =(y1, y2, …, ym ),他们是两个线性表,采用带头结点的单链表存储,设计一个算法合并L1、L2,结果放在线性表L3中。
要求:
L3 = (x1, y1, x2, y2, …, xm, ym, x(m+1), xn) m<=n
L3 = (x1, y1, x2, y2, …, xn, yn, y(n+1), ym) m>n
L3仍采用单链表存储,算法的空间复杂度为O(1)。
思路:由于空间复杂度为O(1),所以可在L1和L2的基础上创建L3,即直接将L1和L2交错链接在L3后面。

算法实现

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>

typedef int ElemType;
typedef struct LNode
{
	ElemType data;
	struct LNode* next;
}LinkNode;

bool DivideList(LinkNode* L1, LinkNode* L2, LinkNode*& L3);		//L1、L2、L3为三个单链表的头结点
bool InitList(LinkNode*& L);		//链表产生
bool DispList(LinkNode* L);			//链表输出

int main(int argc, const char* argv[])
{
	LinkNode* L1 = NULL, * L2 = NULL, * L3 = NULL;
	int x;
	bool flag = false;
	InitList(L1);
	InitList(L2);
	flag = DivideList(L1, L2, L3);
	if (flag)
		printf("算法执行成功。\n");
	else
		printf("算法执行失败。\n");
	DispList(L3);
	return 0;
}

bool InitList(LinkNode*& L)		//建立单链表
{
	while (!L) {
		L = (LinkNode*)malloc(sizeof(LNode));
	}
	L->next = NULL;
	int i, n;
	LinkNode* p = NULL, * q = NULL;
	q = L;
	printf("请输入数据规模:\n");
	scanf("%d", &n);
	printf("请输入数据:\n");
	for (i = 0; i < n; i++) {
		while (!p) {
			p = (LinkNode*)malloc(sizeof(LNode));
		}
		scanf("%d", &p->data);
		q->next = p;
		q = p;
		p = q->next = NULL;
	}
	return true;
}
bool DispList(LinkNode* L)		//输出单链表
{
	LinkNode* p = L->next;
	while (p) {
		printf("\t%d", p->data);
		p = p->next;
	}
	printf("\n");
	return true;
}
bool DivideList(LinkNode* L1, LinkNode* L2, LinkNode*& L3)		//L1、L2、L3为三个单链表的头结点
{
	//直到L3申请成功
	while (!L3) {
		L3 = (LinkNode*)malloc(sizeof(LNode));
	}
	LinkNode* p, * q, * r;
	p = L1->next;		//p为L1的工作指针
	q = L2->next;		//q为L2的工作指针
	r = L3;				//r为L3的尾指针
	//当p和q均不为空时
	while (p && q) {
		r->next = p;	//先接L1
		r = r->next;	//尾指针后移
		p = p->next;	//p指针后移
		r->next = q;	//再接L2
		r = r->next;	//尾指针后移
		q = q->next;	//q指针后移
		r->next = NULL;	//尾指针的next应该置空
	}
	//当p不为空时
	if (p) {
		r->next = p;	//将剩余的接在尾指针后面
	}
	//当q不为空时
	if (q) {
		r->next = q;	//将剩余的接在尾指针后面
	}
	return true;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

☆MOON

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

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

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

打赏作者

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

抵扣说明:

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

余额充值