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