最近暇つぶしに応用情報技術者試験の問題を解いています。
少しでも理解を深めるため、応用情報技術者試験のプログラミング分野の問題をc/c++で実装しました。
令和5年秋の問題となります。
少しでも試験問題の理解の助けになればと思い共有します。
過去問は以下のサイト様より確認しています。
https://www.ap-siken.com/apkakomon_pm.php
注意点
・開発環境はvisual studio 2022 です
・cとc++混じってます
・newで動的確保していますが、deleteとか一切していないです。
コード
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
	int key;
	Node* left;
	Node* right;
}Node;
Node* NewNode(int k)
{
	Node* node = new Node();
	node->key = k;
	return node;
}
Node* search(Node* t, int k)
{
	if(t == NULL)
	{
		return NULL;
	}
	else if(t->key == k)
	{
		return t;
	}
	else if(t->key > k)
	{
		return search(t->left, k);
	}
	else // t->key が k より小さい場合
	{
		return search(t->right, k);
	}
}
Node* insert(Node* t, int k)
{
	if(t == NULL)
	{
		t = NewNode(k);
	}
	else if(t->key > k)
	{
		t->left = insert(t->left, k);
	}
	else if(t->key < k)
	{
		t->right = insert(t->right, k);
	}
	return t;
}
/* 試験問題外 */
int height(Node* t)
{
	if (t == NULL) 
	{
		return 0;
	}
	int leftHeight = height(t->left);
	int rightHeight = height(t->right);
	return 1 + (leftHeight > rightHeight ? leftHeight : rightHeight);
}
Node* rotateR(Node* t)
{
	Node* a = t->left;
	Node* b = a->right;
	a->right = t;
	t->left = b;
	return a;
}
Node* rotateL(Node* t)
{
	Node* a = t->right;
	Node* b = a->left;
	a->left = t;
	t->right = b;
	return a;
}
Node* balance(Node* t)
{
	int h1 = height(t->left) - height(t->right);
	if(h1 == 2)/**ウ***/
	{
		int h2 = height(t->left->right) - height(t->left->left);/**エ**/
		if(h2 > 0)
		{
			t->left = rotateL(t->left);
		}
		t = rotateR(t);
	}
	else if(h1 == -2)/**オ***/
	{
		int h3 = height(t->right->left) - height(t->right->right);/***カ***/
		if(h3 > 0)
		{
			t->right = rotateR(t->right);
		}
		t = rotateL(t);
	}
	return t;
}
Node* insertB(Node* t, int k)
{
	if(t == NULL)
	{
		t = NewNode(k);
	}
	else if(t->key > k)
	{
		t->left = insertB(t->left, k);
	}
	else if(t->key < k)
	{
		t->right = insertB(t->right, k);
	}
	t = balance(t);
	return t;
}
/*試験問題外*/
int space = 0;
void printKeys(Node* node)
{
	if (node == NULL)
	{
		return;
	}
	for (int i = 0; i < space; i++)
	{
		printf("  ");
	}
	// キー値を出力
	printf("%d\n", node->key);
	space++;
	// 左側の子ノードを出力
	printKeys(node->left);
	// 右側の子ノードを出力
	printKeys(node->right);
	space--;
}
int main(void)
{
	Node* node = NULL;
	// 図1
	node = insert(node, 6);
	node = insert(node, 3);	
	node = insert(node, 9);
	node = insert(node, 1);
	node = insert(node, 5);
	// 設問2 (2)
	node = insertB(insertB(node,4),8);
	while(true)
	{
		system("cls");
		space = 0;
		printKeys(node);
		
		printf("\n\n");
		
		int input1, input2;
		scanf_s("%d %d", &input1, &input2);
		if(input1 < 1)
		{
			break;
		}
		if(input1 == 1)
		{
			node = insert(node, input2);
		}
		if(input1 == 2)
		{
			node = insertB(node, input2);
		}
	}
	return 0;
}
説明
コメントの //図1 の箇所で 試験問題の図1を再現。
// 説明2(2)で同様の試験問題の箇所を再現しています。
出力の処理はAIに聞きつつ雑に変更しているため、ゴミコードです。
試験には含まれていないので無視してください。
以下のように出力されます。
非常に分かりづらいです(ツリー形式で出力したかった…)
// 以降はコメントです。実際には出力されません
5    // 一番上のノード
  3    //左の子のノード
    1       // 左の子ノード
    4       // 右の子ノード
  8   // 左の子ノード
    6    // 左の子ノード
    9     // 右の子ノード
また、出力された後以下の形式でノードを追加することができます。
insert関数で10を挿入したい場合
1 10
insertB関数で20を挿入したい場合
2 10
など…
0 0 等の入力で終了します。
以上です。