アルゴリズムへの道 (C++)

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

おすすめ

転載: blog.csdn.net/MOON_YZM/article/details/132025564