1. リンクリスト
1. 2 つの単一リンクリストをマージして同じデータを取得する問題
質問: A と B が 2 つの単一リンク リスト (リード ノード) であり、要素が昇順であるとします。A と B の共通要素から単一リンク リスト C を生成するアルゴリズムを設計してください。 A と B は破棄されていません 分析: 要件は
ノード A と B を破棄することで
はないため、接続するために割り当てられたノード スペースを再作成する必要があります。共通の要素を見つけるために、A の要素をたどるたびに、B の要素と 1 つずつ比較され、その値が別の空間ノードに与えられ、C に接続されます。時間計算量は O(n^2) です。
2 つのリンク リストは昇順であるため、同期的に比較される 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. 2 つの単一リンクリストを 1 つの単一リンクリストにマージする問題
目的: 単一リンク リストの適用とアルゴリズム設計の質問をマスターする
: L1 = (x1, x2, …, xn)、L2 = (y1, y2, …, ym)、これらは 2 つの線形リストであり、次のような単一リンク リストを使用します。先頭ノードを格納するには、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) であるため、L3 は L1 と L2 に基づいて作成できます。つまり、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;
}