<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門 | 基本情報技術者試験 受験ナビ｜科目A・科目B対策から過去問解説まで 250本以上の記事を掲載</title>
	<atom:link href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.seplus.jp/dokushuzemi/ec/fe/fenavi</link>
	<description>基本情報技術者試験を学習する人のためにつくられた専門メディア。250本以上の記事を掲載し、勉強方法や各分野のポイント、過去問解説など、試験に役立つ情報を発信。試験対策書籍を執筆する著者が、はじめて学ぶ人でもわかりやすく解説します。（2023年度からの新制度に対応済み）</description>
	<lastBuildDate>Mon, 20 Apr 2026 07:08:52 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.9.29</generator>
	<item>
		<title>マージソート｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</title>
		<link>https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/margesort/</link>
		<pubDate>Mon, 11 Dec 2023 09:22:58 +0000</pubDate>
		<dc:creator><![CDATA[矢沢 久雄]]></dc:creator>
				<category><![CDATA[アルゴリズム]]></category>
		<category><![CDATA[科目 B]]></category>
		<category><![CDATA[過去問演習]]></category>

		<guid isPermaLink="false">https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/?post_type=similar_programming&#038;p=8101</guid>
		<description><![CDATA[<p>基本情報技術者試験は、2023年4月から新制度で実施されています。 この連載では、新制度の擬似言語（旧制度の擬似言語とは、表記方法に違いがあります）を使って、試験のシラバス（情報処理技術者試験における知識・技能の細目）に [&#8230;]</p>
<p>The post <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/margesort/">マージソート｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</a> first appeared on <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi">基本情報技術者試験 受験ナビ｜科目A・科目B対策から過去問解説まで 250本以上の記事を掲載</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>基本情報技術者試験は、2023年4月から新制度で実施されています。</p>
<p>この連載では、新制度の擬似言語（旧制度の擬似言語とは、表記方法に違いがあります）を使って、試験のシラバス（情報処理技術者試験における知識・技能の細目）に示されている代表的なアルゴリズムとデータ構造を、プログラミング入門者向けにやさしく解説します。受験対策としてだけでなく、アルゴリズムとプログラミングの基礎知識を習得するために、ぜひお読みください。</p>
<style>pre{background:#263238!important;border-radius:unset;}pre:not([class*="language-"]){font-family:'Courier New',"HCo Gotham SSm",Gotham,"ヒラギノ角ゴ Pro W3","Hiragino Kaku Gothic ProN","Hiragino Sans","BIZ UDPGothic",Meiryo,sans-serif!important;color:#ccc;font-size:1em;padding:1em;}ol.background{padding-left:3em!important;}@media only screen and (max-width:600px){ol{padding-left:1em}dd{margin-left:2em}}.underline{border-bottom:1px solid;}code{padding: 0.15em 0.25em;}pre, code{background: #263238;color: #eceff1;border-radius: unset;font-size: 1em;line-height: 1.8;position: relative;}article, pre, code {
    font-family: 'consolas','Courier New',"HCo Gotham SSm",Gotham,"ヒラギノ角ゴ Pro W3","Hiragino Kaku Gothic ProN","Hiragino Sans","BIZ UDPGothic",Meiryo,sans-serif!important;
}
img{width: 100%;}
article, pre, code {font-family: "Courier New","HCo Gotham SSm",Gotham,"ヒラギノ角ゴ Pro W3","Hiragino Kaku Gothic ProN","Hiragino Sans","BIZ UDPGothic",Meiryo,sans-serif!important;}
</style>
<p>今回は、「 <span class="bold">マージソート</span> 」というアルゴリズムを取り上げます。</p>
<h2>マージソートの基本的な手順</h2>
<p>はじめに、マージソートの基本的な手順を説明します。</p>
<p>マージソートのマージ（merge）は、「結合する」という意味です。<br />
<span class="underline">マージソートは、2つのソート済みの配列を結合して、ソートされた1つの配列にします。</span> </p>
<p>例として、図1を見てください。</p>
<figure style="display:block;width:350px;margin: 0 auto;"><figcaption>図1　ソート済みの配列Aと配列Bを結合して、ソートされた1つの配列Cにする</figcaption><div class="material-placeholder"><img src="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/wp-content/uploads/2023/12/795316b92fc766b0181f6fef074f03fa-e1702292302448.jpg" alt=""></div>
</figure>
<p>昇順にソートされた配列Aと配列Bがあります。<br />
これらを結合して、昇順にソートされた1つの配列Cにしてみましょう。</p>
<p>配列Aと配列Bは、昇順にソートされているのですから、それぞれの先頭の要素を比較して小さい方を取り出し、それを配列Cに格納することを繰り返せば、昇順にソートされた1つの配列になります。この手順を繰り返すと、配列Aの要素が先に無くなるので、配列Bに残った要素は、そのまま取り出して配列Cに格納します。</p>
<p>図2にマージソートが完了するまでの手順を示します。</p>
<p>図2　マージソートが完了するまでの手順</p>
<figure style="display:block;width:350px;margin: 0 auto;">
<div class="material-placeholder"><img src="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/wp-content/uploads/2023/12/5db501bbbfaf224db26522b7dd2d0f43.jpg" alt=""></div>
</figure>
<figure style="display:block;width:350px;margin: 0 auto;">
<div class="material-placeholder"><img src="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/wp-content/uploads/2023/12/4f4d4c26c116b915f460b98308f465e7.jpg" alt=""></div>
</figure>
<h2>1つの配列をマージソートする方法</h2>
<p>マージソートは、2つのソート済みの配列を結合することでソートしますが、1つの配列をソートすることもできます。そのためには、結合の前に分割の処理を行います。</p>
<p>例として、図3を見てください。</p>
<figure style="display:block;width:350px;margin: 0 auto;"><figcaption style="display:block;width:350px;margin: 0 auto;">図3　分割と結合で1つの配列をマージソートする手順</figcaption><div class="material-placeholder"><img src="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/wp-content/uploads/2023/12/c8856789ec11ab8b1013037cef6929f9-e1702292350773.jpg" alt=""></div>
</figure>
<p>ソート前の配列には要素数が4個ありますが、これを要素数1個の4つの配列になるまで分解すれば、ソート済みの配列が4つになります（要素数が1個の配列は、ソートされているとみなせます）。<br />
ソート済みの4つの配列を2つずつ結合すると、ソートされた2つの配列になります。<br />
さらに、ソート済みの2つの配列を結合すると、ソートされた1つの配列になります。</p>
<h2>マージソートのプログラムの例</h2>
<p>マージソートのプログラムの例を示しましょう。</p>
<p>リスト1は、旧制度の平成22年度春期試験の問8に示された「マージソート」のプログラムを、現行制度の擬似言語の記述形式にしたものです。</p>
<p><span class="chip">リスト1　マージソートのプログラムの例（出典：H22春問8改）<i class="material-icons blue-text mag_w05">code</i></span></p>
<pre>
    <code>
// 手続Sortの定義（ここから）
〇Sort(整数型の配列：list, 整数型：num)
  整数型の配列：slist1, slist2
  整数型：i, num1, num2
  // 配列listの要素数が1より大きいなら（分割可能なら）処理を行う
  if (num ＞ 1)
    // 配列listを配列slist1と配列slist2に分割する
    num1 ← num ÷ 2
    num2 ← num － num1
    for (iを0から、i ＜ num1である限り、1ずつ増やす)
      slist1[i] ← list[i]
    endfor
    for (iを0から、i ＜ num2である限り、1ずつ増やす)
      slist1[i] ← list[num1 ＋ i]
    endfor
    // 分割した前側の配列list1を手続Sortの再帰呼び出しで分割する
    Sort(slist1, num1)
    // 分割した後側の配列list2を手続Sortの再帰呼び出しで分割する
    Sort(slist2, num2)
    // 手続Mergeでlist1とlist2を結合してlist1に格納する
    Merge(slist1, num1, slist2, num2, list)
  endif
// 手続Sortの定義（ここまで）

// 手続Mergeの定義（ここから）
○Merge(整数型の配列slist1, 整数型：num1,
        整数型の配列slist2, 整数型：num2,
        整数型の配列：list)
  整数型：i, j
  i ← 0
  j ← 0
  // 配列slist1と配列slist2の先頭の要素を比較して小さい方を取り出し、
  // それを配列listに格納することを繰り返す
  while ((i ＜ num1) and (j ＜ num2))
    if (slist1[i] ＜ slist2[j])
      list[i + j] ← slist1[i]
      i ← i ＋ 1
    else
      list[i + j] ← slist2[j]
      j ← ｊ ＋ 1
    endif
  endwhile
  // 配列slist1に要素が残っていたら、要素を取り出して配列listに格納する
  while (i ＜ num1)
    list[i + num2] ← slist1[i]
    i ← i ＋ 1
  endwhile
  // 配列slist2に要素が残っていたら、要素を取り出して配列listに格納する
  while (j ＜ num2)
    list[j + num1] ← slist2[j]
    j ← j ＋ 1
  endwhile
// 手続Mergeの定義（ここまで）
    </code>
</pre>
<p>手続Sortは、配列をマージソートします。<br />
引数listにソートする配列を指定し、引数numに配列の要素数を指定します。<br />
手続Mergeは、2つの配列を結合します。<br />
引数slist1、num1、slist2、num2に結合する2つの配列とそれぞれの要素数を指定し、引数listに結合した要素を格納する配列を指定します。<br />
ここでは、配列の大きさが省略されていますが、必要な領域が確保されているとします。<br />
配列の要素番号は、0から始まるとします。</p>
<p>手続Sortの処理の中で、手続Mergeを呼び出しています。<br />
手続Sortの処理の中で、手続Sortを呼び出している部分もあります。<br />
これは、再帰呼び出し（関数や手続の処理の中で、同じ関数や手続を呼び出すことで繰り返しを実現する技法）です。<br />
マージソートの分割や結合の繰り返しは、whileやforを使った表現で記述することが困難なのですが、再帰呼び出しで記述すれば容易です。</p>
<p>リスト1は、大雑把に説明すると以下のような手順です。</p>
<ol>
<li>手続Sortで配列listを配列slist1と配列slist2に分割する</li>
<li>分割した前側の配列list1を手続Sortで分割する（再帰呼び出し）</li>
<li>分割した後側の配列list2を手続Sortで分割する（再帰呼び出し）</li>
<li>手続Mergeでlist1とlist2を結合してlist1に格納する</li>
</ol>
<p>「こんな手順で上手く行くのだろうか？」と疑問に思うかも知れませんが、上手く行ってしまうのが、再帰呼び出しの便利で面白いところです。</p>
<h2>マージソートのプログラムのトレースにチャレンジ</h2>
<p>最後に、先ほどリスト1に示したプログラムのトレースにチャレンジしてみましょう（実際の試験問題にも、プログラムのトレースに関する設問がありました）。<br />
トレースすれば、「こんな手順で上手く行くのだろうか？」という疑問が晴れるはずです。</p>
<p>ここでは、引数listに{3, 8, 2, 7, 5, 1}を、引数numに6を指定して、手続Sortを呼び出したとします。<br />
図4にトレースの結果を示しますので、リスト1の内容と照らし合わせてください。<br />
分割は、配列の前側、前側と進んで、前側の分割が終わったら、後側の分割に進みます。<br />
前側と後側の要素が1つになったら結合が行われます。</p>
<p>マージソートのプログラムのトレースの結果</p>
<div class="card-panel mag_h30">
（1）{3, 8, 2, 7, 5, 1}が、{3, 8, 2}と{7, 5, 1}に分割される。<br />
（2）{3, 8, 2}が、{3}と{8, 2}に分割される。<br />
（3）{8, 2}が、{8}と{2}に分割される。<br />
（4）{8}と{2}が、{2, 8}に結合される。<br />
（5）{3}と{2, 8}が、{2, 3, 8}に結合される。<br />
（6）{7, 5, 1}が、{7}と{5, 1}に分割される。<br />
（7）{5, 1}が、{5}と{1}に分割される。<br />
（8）{5}と{1}が、{1, 5}に結合される。<br />
（9）{7}と{1, 5}が、{1, 5, 7}に結合される。<br />
（10）{2, 3, 8}と{1, 5, 6}が、{1, 2, 3, 5, 7, 8}に結合される（ソート完了）。
</div>
<p>☆　　　☆　　　☆</p>
<p>今回は、「マージソート」というアルゴリズムを取り上げました。</p>
<p>この連載は、今回で最終回です。これまで記事をお読みいただいた読者の皆様に、この場をお借りして厚く御礼申し上げます。</p>
<p>それでは、またどこかでお会いしましょう！</p><p>The post <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/margesort/">マージソート｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</a> first appeared on <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi">基本情報技術者試験 受験ナビ｜科目A・科目B対策から過去問解説まで 250本以上の記事を掲載</a>.</p>]]></content:encoded>
			</item>
		<item>
		<title>二分木の深さ優先探索と幅優先探索｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</title>
		<link>https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/binarytree-dfsandbfs/</link>
		<pubDate>Tue, 14 Nov 2023 05:34:16 +0000</pubDate>
		<dc:creator><![CDATA[矢沢 久雄]]></dc:creator>
				<category><![CDATA[アルゴリズム]]></category>
		<category><![CDATA[科目 B]]></category>

		<guid isPermaLink="false">https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/?post_type=similar_programming&#038;p=8076</guid>
		<description><![CDATA[<p>基本情報技術者試験は、2023年4月から新制度で実施されています。 この連載では、新制度の擬似言語（旧制度の擬似言語とは、表記方法に違いがあります）を使って、試験のシラバス（情報処理技術者試験における知識・技能の細目）に [&#8230;]</p>
<p>The post <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/binarytree-dfsandbfs/">二分木の深さ優先探索と幅優先探索｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</a> first appeared on <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi">基本情報技術者試験 受験ナビ｜科目A・科目B対策から過去問解説まで 250本以上の記事を掲載</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>基本情報技術者試験は、2023年4月から新制度で実施されています。</p>
<p>この連載では、新制度の擬似言語（旧制度の擬似言語とは、表記方法に違いがあります）を使って、試験のシラバス（情報処理技術者試験における知識・技能の細目）に示されている代表的なアルゴリズムとデータ構造を、プログラミング入門者向けにやさしく解説します。<br />
受験対策としてだけでなく、アルゴリズムとプログラミングの基礎知識を習得するために、ぜひお読みください。</p>
<style>pre{background:#263238!important;border-radius:unset;}pre:not([class*="language-"]){font-family:'Courier New',"HCo Gotham SSm",Gotham,"ヒラギノ角ゴ Pro W3","Hiragino Kaku Gothic ProN","Hiragino Sans","BIZ UDPGothic",Meiryo,sans-serif!important;color:#ccc;font-size:1em;padding:1em;}ol.background{padding-left:3em!important;}@media only screen and (max-width:600px){ol{padding-left:1em}dd{margin-left:2em}}.underline{border-bottom:1px solid;}code{padding: 0.15em 0.25em;}pre, code{background: #263238;color: #eceff1;border-radius: unset;font-size: 1em;line-height: 1.8;position: relative;}article, pre, code {
    font-family: 'consolas','Courier New',"HCo Gotham SSm",Gotham,"ヒラギノ角ゴ Pro W3","Hiragino Kaku Gothic ProN","Hiragino Sans","BIZ UDPGothic",Meiryo,sans-serif!important;
}
img{width: 100%;}
article, pre, code {font-family: "Courier New","HCo Gotham SSm",Gotham,"ヒラギノ角ゴ Pro W3","Hiragino Kaku Gothic ProN","Hiragino Sans","BIZ UDPGothic",Meiryo,sans-serif!important;}
</style>
<p>今回は、「 <span class="bold">二分木</span> 」というデータ構造と「 <span class="bold">深さ優先探索</span> 」「 <span class="bold">幅優先探索</span> 」というアルゴリズムを取り上げます。</p>
<h2>二分木とは？ 深さ優先探索、幅優先探索とは？</h2>
<p>「二分木」は、 <span class="underline">1つの要素（データ）が2つの要素につながることを繰り返したデータ構造</span> です。二分木の形式には、探索を効率的に行える「二分探索木」や、整列を効率的に行える「ヒープ」などがありますが、この記事では、二分木のすべての要素をたどるアルゴリズムをテーマにします。</p>
<p>単純なデータ構造である1次元配列であれば、すべての要素をたどるのは、とても簡単です。1次元配列の先頭から末尾まで、要素番号の順に要素をたどればよいからです。<br />
それに対して、二分木のすべての要素をたどるのは、やや困難です。様々なたどり方が考えられるからです。もしも、たどり方の手順に不備があると、いくつかの要素をたどれない場合もあります。</p>
<p>二分木のすべての要素を確実にたどるアルゴリズムには、<br />
「 <span class="underline">深さ優先探索（DFS＝Depth First Search）</span> 」と「 <span class="underline">幅優先探索（BFS＝Breadth First Search）</span> 」があります。</p>
<p>深さ優先探索の例を図1に、幅優先探索の例を図2に示します。</p>
<p>1次元配列を図示するときは、要素を四角形で示しますが、二分木を図示するときは、慣例として要素を円で示します。円と円をつなぐ線で、要素のつながりを示します。<br />
ここでは、A～Gが要素です。1～7は、要素をたどる順序です。</p>
<figure style="display:inline-block;width:48%;min-width:250px;"><figcaption>図1　深さ優先探索の例</figcaption><div class="material-placeholder"><img src="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/wp-content/uploads/2023/11/795316b92fc766b0181f6fef074f03fa.jpg" alt=""></div>
</figure>
<figure style="display:inline-block;width:48%;min-width:250px;"><figcaption>図2　幅優先探索の例</figcaption><div class="material-placeholder"><img src="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/wp-content/uploads/2023/11/2b530e80c7d0de90885e285c5d798063.jpg" alt=""></div>
</figure>
<p>二分木の根元にある要素を「根」と呼びます。<br />
<span class="underline">深さ優先探索</span> では、根（A）から始めて、どんどん先の要素に（深い向きに）たどっていきます。左右の2つの要素がある場合は、先に左側をたどり、左側が末端になったら右側をたどります。<br />
図1の場合は、左側にA→B→Dとたどって末端になり、右側のEにたどって末端になり、右側のCから左側のFにたどって末端になり、右側のGにたどります。</p>
<p><span class="underline">幅優先探索</span> では、根（A）から始めて、直接つながっている要素を左から右の横に（幅の向きに）たどっていきます。<br />
図2の場合は、Aに直接つながっているA→B→Cとたどり、Bに直接つながっているD→Eとたどり、Cに直接つながっているF→Gをたどります。</p>
<h2>深さ優先探索のプログラムを見てみよう</h2>
<p>2022年12月に公開された科目Bサンプル問題セットの問9に、深さ優先探索を行うプログラムが示されています。<br />
深さ優先探索を行うには、以下の2つの方法があります。<br />
・再帰呼び出し（関数や手続の処理の中で、同じ関数や手続を呼び出して、繰り返しを実現するプログラミング技法）を使う<br />
・スタック（後入れ先出し形式のバッファ）を使う</p>
<p>この問題では、再帰呼び出しを使っています。<br />
深さ優先探索の具体例として、プログラムの内容を見てみましょう。以下に問題を示します。</p>
<div class="card-panel mag_h30">
<h3>問９</h3>
<p>次の記述中の<span class="blank"></span>に入れる正しい答えを，解答群の中から選べ。ここで， 配列の要素番号は 1 から始まる。 </p>
<p><p>手続 order は，図の2分木の，引数で指定した節を根とする部分木をたどりながら，全ての節番号を出力する。大域の配列 tree が図の2分木を表している。<br />
配列 tree の要素は，対応する節の子の節番号を，左の子，右の子の順に格納した配列である。例えば，配列 tree の要素番号1の要素は，節番号1の子の節番号から成る配列であり，左の子の節番号2，右の子の節番号3を配列｛2，3｝として格納する。 <br />
手続 order を order(1)として呼び出すと，<span class="blank"></span>の順に出力される。</p>
<figure><figcaption>図 プログラムが扱う 2 分木</figcaption><div class="material-placeholder center"><img src="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/wp-content/uploads/2023/11/ec52f19a62171cae654235b3b492b877.jpg" alt="" style="max-width: 600px;"></div>
</figure>
<p><span class="chip">プログラム<i class="material-icons blue-text mag_w05">code</i></span></p>
<pre>
    <code>
大域: 整数型配列の配列: tree ← {{2, 3}, {4, 5}, {6, 7}, {8, 9},{10, 11}, {12, 13}, {14}, {}, {}, {}, {}, {}, {}, {}} // {}は要素数0の配列	

○order(整数型: n)
    if (tree[n]の要素数 が 2 と等しい) 
        order(tree[n][1]) 
        nを出力
        order(tree[n][2]) 
    elseif (tree[n]の要素数 が 1 と等しい) 
        order(tree[n][1]) 
        nを出力 
    else 
        nを出力 
    endif 
    </code>
</pre>
<p>
解答群<br />
　ア 1，2，3，4，5，6，7，8，9，10，11，12，13，14<br />
　イ 1，2，4，8，9，5，10，11，3，6，12，13，7，14<br />
　ウ 8，4，9，2，10，5，11，1，12，6，13，3，14，7<br />
　エ 8，9，4，10，11，5，2，12，13，6，14，7，3，1
</p>
</div>
<p>問題に示されたプログラムは、大域の整数型の配列の配列（以下、2次元配列と呼びます）treeと、引数nで指定された要素を基点として深さ優先探索を行う手続orderから構成されています。<br />
手続orderをorder(1)として呼び出すと、どのような順で要素が出力されるかを答えます。<br />
配列の要素番号は1から始まるとしているので、order(1)は、二分木の根からすべての要素をたどります。この問題では、2次元配列の要素を「要素」と呼び、二分木の要素を「節」と呼んでいますが、これ以降の説明では、どちらも「要素」と呼びます。
</p>
<p>問題の図に示された二分木と2次元配列treeの要素を見比べて、プログラムで二分木がどのように表現されているのかを理解してください（二分木の表現方法は、いろいろあります。このプログラムの表現方法は、その一例です）。<br />
図の注記1から、2次元配列treeの要素番号が、図の二分木の円の中に示された数字に対応していることがわかります。2次元配列treeの個々の要素の1番目の要素の値（2次元配列は、要素が1次元配列であり、その１次元配列の中に要素の値があります）が、左側につながっている要素の要素番号を示し、2番目の要素が、右側につながっている要素の要素番号を示しています。</p>
<p>たとえば、2次元配列treeの1番目の要素は {2, 3} です。<br />
これは、この要素が①に対応し、①の左側が②であり、①の右側が③であることを示しています。<br />
｛7｝ のように、要素が1つだけの場合は、図の注記2から、左側の要素を示している（左側だけに要素がある）ことがわかります。要素がない { } は、その先につながる要素がないことを示しています。</p>
<p>手続orderは、再帰呼び出しで、深さ優先探索を行っています。<br />
ここでは、すべての要素をたどるだけでなく、要素の値の出力も行っています（画面への出力なら表示されます）。手続orderの処理内容は、if文で3つに分けられています。</p>
<p>「tree[n]の要素が2と等しい」という条件が真なら、要素nの先に2つの要素がつながっています。<br />
この場合には、左側の要素を意味するtree[n][1]を引数に指定して、手続orderを再帰呼び出しします。<br />
これによって、左側にたどることになります。<br />
左側がたどり終わったら、「nを出力」してから、右側の要素を意味するtree[n][2]を引数に指定して手続orderを再帰呼び出しします。これによって、右側にたどることになります。</p>
<p>「tree[n]の要素が1と等しい」という条件が真なら、要素nの先に1つの要素（左側の要素）だけがつながっています。<br />
この場合には、左側の要素を意味するtree[n][1]を引数に指定して、手続orderを再帰呼び出しします。これによって、左側にたどることになります。<br />
左側が終わったら「nを出力」します。右側には要素がないのですから、右側にはたどりません。</p>
<p>上記の2つの条件が真でないなら、要素nの先に要素がない、つまり、要素nが末端ということです。この場合には、「nを出力」するだけです。</p>
<p>手続orderの処理内容がわかったら、図に示された二分木の要素が、どういう順番で出力されるかがわかるでしょう。<br />
問題の解答群を見ると、最初から3番目までに出力される要素がわかれば、答えを選べます。<br />
まず、根の要素①から左側にたどって、末端の要素⑧が出力されます。<br />
次に、⑧の上にある④が出力されてから、④の右側にたどって、<br />
末端の⑨が出力されます。</p>
<p>ここまでの出力は、⑧、④、⑨であり、選択肢ウが正解です。</p>
<p><span class="underline">正解：ウ</span> </p>
<h2>VBScriptでプログラムを実行してみよう</h2>
<p>擬似言語で示されたプログラムを見ただけでは、再帰呼び出しで深さ優先探索を実現するイメージがつかめない、という人もいらっしゃると思いますので、先ほどの問題に示されたプログラムと同様の機能のプログラムを、VBScript（Visual Basic Scripting Edition）で作成して実行してみましょう。<br />
VBScriptは、Windowsパソコンであれば、何もツールをインストールせずに、すぐに実行できるプログラミング言語です。</p>
<p>リスト1に示したプログラムを、dfs.vbsというファイル名で任意のディレクトリに保存してください。ここでは、C:\testというディレクトリに保存しています。<br />
Windowsのコマンドプロンプトを起動して、カレントディレクトリをC:\testに移動したら、「cscript dfs.vbs」と入力して「Enter」キーを押せば、プログラムを実行できます。<br />
プログラムの実行結果の例を図3に示します。先ほどの問題の解答群の選択肢ウと同じ出力が得られました。</p>
<div class="card-panel mag_h30">
<p>リスト1　VBScriptで作成した深さ優先探索のプログラム</p>
<p>&#8216; 大域の整数型の配列の配列<br />
tree = Array(Array(2, 3), Array(4, 5), Array(6, 7), Array(8, 9), _<br />
             Array(10, 11), Array(12, 13), Array(14), Array(), Array(), Array(), _<br />
             Array(), Array(), Array(), Array())  &#8216; Array()は要素数0の配列</p>
<p>&#8216; 手続orderの定義<br />
Sub order(n)<br />
  &#8216; 試験問題の配列の要素番号は1から始まり<br />
  &#8216; VBScriptの配列の要素番号は0から始まるので<br />
  &#8216; n &#8211; 1を代入したidxでVBScriptの配列を取り扱う<br />
  idx = n &#8211; 1</p>
<p>  &#8216; tree(n)の要素数が2の場合<br />
  If UBound(tree(idx)) + 1 = 2 Then<br />
    order(tree(idx)(0))<br />
    WScript.StdOut.Write(n &#038; &#8220;, &#8220;)<br />
    order(tree(idx)(1))<br />
  &#8216; tree(n)の要素数が1の場合<br />
  ElseIf UBound(tree(idx)) + 1 = 1 Then<br />
    order(tree(idx)(0))<br />
    WScript.StdOut.Write(n &#038; &#8220;, &#8220;)<br />
  &#8216; tree(n)の要素数が0の場合<br />
  Else<br />
    WScript.StdOut.Write(n &#038; &#8220;, &#8220;)<br />
  End If<br />
End Sub</p>
<p>&#8216; 手続orderをorder(1)として呼び出す<br />
order(1)<br />
&#8216; 最後に改行する<br />
WScript.StdOut.WriteLine()
</p></div>
<figure><figcaption>図3　リスト1の実行結果の例</figcaption><div class="material-placeholder"><img src="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/wp-content/uploads/2023/11/c8856789ec11ab8b1013037cef6929f9.png" alt=""></div>
</figure>
<p>リスト1のポイントとなる部分（問題に示された擬似言語のプログラムと表現が大きく異なる部分）を説明しましょう。<br />
VBScriptでは、Array関数の引数に要素をカンマで区切って指定して、配列を作成します。<br />
ここでは、2次元配列なので、Array関数の引数でArray関数を使って、配列の配列を作成しています。引数がないArray関数は、要素がない配列を作成します。VBScriptでは、長い命令を途中で改行するときに、行の末尾にアンダースコア（ _ ）を置きます。</p>
<p>問題のプログラムでは、要素番号が1から始まりますが、VBScriptでは要素番号が0から始まるので、手続orderの中でidx = n &#8211; 1という処理を行い、変数idxにVBScript用の要素番号を得ています。UBound関数は、引数に指定された配列の末尾の要素の要素番号を返します。これに1を足すことで、要素数が得られます（VBScriptでは要素番号が0から始まるからです）。<br />
擬似言語では、配列の要素番号を [ ] で囲みますが、VBScriptでは ( ) で囲みます。WScript.StdOut.Write(n &#038; &#8220;, &#8220;)は、nの値とカンマを表示します（表示の末尾で改行しません）。WScript.StdOut.WriteLine()は、改行だけを行います。<br />
その他の部分は、問題に示された擬似言語のプログラムと同様です。</p>
<p>☆　　　☆　　　☆</p>
<p>今回は、「二分木」というデータ構造と「深さ優先探索」「幅優先探索」というアルゴリズムを取り上げました。</p>
<p>次回も、シラバスに示されたアルゴリズムとデータ構造を解説します。<br />
それでは、またお会いしましょう！</p><p>The post <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/binarytree-dfsandbfs/">二分木の深さ優先探索と幅優先探索｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</a> first appeared on <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi">基本情報技術者試験 受験ナビ｜科目A・科目B対策から過去問解説まで 250本以上の記事を掲載</a>.</p>]]></content:encoded>
			</item>
		<item>
		<title>比べてわかるキューとスタックの仕組み｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</title>
		<link>https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/queueandstack/</link>
		<pubDate>Thu, 05 Oct 2023 04:37:23 +0000</pubDate>
		<dc:creator><![CDATA[矢沢 久雄]]></dc:creator>
				<category><![CDATA[アルゴリズム]]></category>
		<category><![CDATA[科目 B]]></category>
		<category><![CDATA[過去問演習]]></category>

		<guid isPermaLink="false">https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/?post_type=similar_programming&#038;p=8057</guid>
		<description><![CDATA[<p>基本情報技術者試験は、2023年4月から新制度で実施されています。 この連載では、新制度の擬似言語（旧制度の擬似言語とは、表記方法に違いがあります）を使って、試験のシラバス（情報処理技術者試験における知識・技能の細目）に [&#8230;]</p>
<p>The post <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/queueandstack/">比べてわかるキューとスタックの仕組み｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</a> first appeared on <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi">基本情報技術者試験 受験ナビ｜科目A・科目B対策から過去問解説まで 250本以上の記事を掲載</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>基本情報技術者試験は、2023年4月から新制度で実施されています。</p>
<p>この連載では、新制度の擬似言語（旧制度の擬似言語とは、表記方法に違いがあります）を使って、試験のシラバス（情報処理技術者試験における知識・技能の細目）に示されている代表的なアルゴリズムとデータ構造を、プログラミング入門者向けにやさしく解説します。受験対策としてだけでなく、アルゴリズムとプログラミングの基礎知識を習得するために、ぜひお読みください。</p>
<style>pre{background:#263238!important;border-radius:unset;}pre:not([class*="language-"]){font-family:'consolas','Courier New',"HCo Gotham SSm",Gotham,"ヒラギノ角ゴ Pro W3","Hiragino Kaku Gothic ProN","Hiragino Sans","BIZ UDPGothic",Meiryo,sans-serif!important;color:#ccc;font-size:1em;padding:1em;}ol.background{padding-left:3em!important;}@media only screen and (max-width:600px){ol{padding-left:1em}dd{margin-left:2em}}.underline{border-bottom:1px solid;}code{padding: 0.15em 0.25em;}pre, code{background: #263238;color: #eceff1;border-radius: unset;font-size: 1em;line-height: 1.8;position: relative;}article, pre, code {
    font-family: 'consolas','Courier New',"HCo Gotham SSm",Gotham,"ヒラギノ角ゴ Pro W3","Hiragino Kaku Gothic ProN","Hiragino Sans","BIZ UDPGothic",Meiryo,sans-serif!important;
}
img{width: 100%;}</style>
<p>今回は、「 <span class="bold">キュー</span> 」と「 <span class="bold">スタック</span> 」のデータ構造を取り上げます。</p>
<h2>キューとスタックの特徴</h2>
<p>プログラムでは、すぐに処理しないデータを一時的に格納しておく配列が必要になる場合があります。このような配列をバッファ（buffer＝緩衝器）と呼びます。<br />今回のテーマであるキューとスタックは、どちらもバッファですが、配列へのデータの格納と取り出しの順序に違いがあります。キューとスタックを比べてみましょう。</p>
<p><span class="bold">キュー</span> は、ごく普通のバッファであり、最初に格納したデータを最初に取り出します。これをFIFO（First In First Out＝先入れ先出し）形式と呼びます。</p>
<p>たとえば、&#8221;A&#8221;、&#8221;B&#8221;（ここでは、文字列データを格納するとします）の順にキューに格納したら、&#8221;A&#8221;、&#8221;B&#8221;の順に取り出します。<br />キュー（queue）は、「待ち行列」という意味です。日常生活において、何かの切符を買う窓口では、最初に列に並んだ人（First In）が、最初に列から出て（First Out）切符を買います。プログラムのキューも、これと同様です。<br />キューにデータを格納することをエンキュー（enqueue）、キューからデータを取り出すことをデキュー（dequeue）と呼びます（図1）。</p>
<figure><figcaption>図1　キューはFIFO形式のバッファである</figcaption><div class="material-placeholder center"><img src="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/wp-content/uploads/2023/10/795316b92fc766b0181f6fef074f03fa.jpg" alt="" style="width: 300px;"></div>
</figure>
<p><span class="bold">スタック</span> は、ちょっと変わったバッファであり、最後に格納したデータを最初に取り出します。これをLIFO（Last In First Out＝後入れ先出し）形式と呼びます。</p>
<p>たとえば、&#8221;A&#8221;、&#8221;B&#8221;の順にスタックに格納したら、&#8221;B&#8221;、&#8221;A&#8221;の順に取り出します。<br />スタック（stack）は、「干し草を積んだ山」という意味です。日常生活において、牧場で家畜に食べさせる草を積んだ山では、最後に積んだ草（Last In）を、最初に取り出します（First Out）。プログラムのスタックも、これと同様です。<br />スタックにデータを格納することをプッシュ（push）、スタックからデータを取り出すことをポップ（pop）と呼びます（図2）。</p>
<figure><figcaption>図2　スタックはLIFO形式のバッファである</figcaption><div class="material-placeholder center"><img src="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/wp-content/uploads/2023/10/2b530e80c7d0de90885e285c5d798063.jpg" alt="" style="max-width: 650px;"></div>
</figure>
<p>キューとスタックの大きな違いは、<span class="underline">順序が入れ替わるかどうか</span>です。<br /><span class="bold">キュー</span> では、&#8221;A&#8221;、&#8221;B&#8221;の順に格納すれば、&#8221;A&#8221;、&#8221;B&#8221;の順に取り出されるので、順序が入れ替わりません。<br /><span class="bold">スタック</span> では、&#8221;A&#8221;、&#8221;B&#8221;の順に格納すれば、&#8221;B&#8221;、&#8221;A&#8221;の順に取り出されるので、順序が入れ替わります。</p>
<h2>キューとスタックをオブジェクトで実現する</h2>
<p>プログラムでキューとスタックを実現するには、データを格納する配列と、その配列にデータの格納および取り出しを行う処理を用意することになります。</p>
<p>現時点で公開されている基本情報技術者試験の問題を見ると、これらの仕組みをオブジェクトとして実現しています。オブジェクトとは、内部にいくつかのデータと処理を持つモジュール（プログラムの構成要素）です。</p>
<p>基本情報技術者試験の擬似言語では、オブジェクトが持つデータをメンバ変数と呼び、オブジェクトが持つ処理をメソッドと呼びます。<br />キューやスタックを実現するオブジェクトは、メンバ変数として配列を持ち、その配列にデータを格納するメソッド、およびデータを読み出すメソッドを持つことになります。他にも、必要なメソッドがあれば用意します。</p>
<p>プログラムでは、オブジェクトをクラスとして定義します。<br />プログラムの実行時に、クラス一式（データと処理の一式）をメモリにロードしたものが、オブジェクト（クラスのインスタンスとも呼びます）です。<br />オブジェクトが持つメンバ変数やメソッドは、「オブジェクト名.メンバ変数名」や「オブジェクト名.メソッド名」という構文で使います。多くの場合に、オブジェクトを使う側は、オブジェクトが持つデータを直接操作せずに、オブジェクトが持つメソッドを使って間接的に操作します。</p>
<p>キューを実現するQueueクラスを作成したとしましょう。<br />このQueueクラスには、キューの実体となる配列、コンストラクタQueue、キューにデータを格納するenqueueメソッド、キューから取り出したデータを返すdequeueメソッド、およびキューに格納されているデータ数を返すsizeメソッドがあるとします。<br />これらは、後で示す試験問題のプログラムに似せたものです。<br />コンストラクタとは、クラス一式をメモリにロードする（オブジェクトを生成する）機能を持った特殊なメソッドです。多くのプログラミング言語で、コンストラクタの名前はクラスと同じにします。Queueクラスのコンストラクタの名前は、Queueです。</p>
<p>リスト1は、Queueクラスを使ったプログラムの例です。</p>
<p>ここでは、queueという名前のキューを生成し、キューに&#8221;A&#8221;と&#8221;B&#8221;というデータを格納して、キューからすべてのデータを取り出して表示しています。</p>
<p>キューは、FIFO形式なので、&#8221;A&#8221;、&#8221;B&#8221;の順に表示されます。<br />ここでは、「クラス名：オブジェクト名 ← コンストラクタ()」という構文で、オブジェクトを生成しています。これは、後で示す試験問題のプログラムに合わせたものです。<br />多くのプログラミング言語では、オブジェクトの生成にnewという命令を使いますが、擬似言語では使いません。</p>
<p><span class="chip">リスト1　Queueクラスを使ったプログラムの例<i class="material-icons blue-text mag_w05">code</i></span></p>
<pre>
    <code>
// キューを生成する
Queue:queue ← Queue()

// キューにデータを格納する
queue.enqueue("A")
queue.enqueue("B")

// キューからすべてのデータを取り出す
while (queue.size() ＞ 0)
  queue.dequeue()の戻り値を表示する
endwhile
    </code>
</pre>
<p>スタックを実現するStackクラスを作成したとしましょう。<br />このStackクラスには、スタックの実体となる配列、コンストラクタStack、スタックにデータを格納するpushメソッド、スタックから取り出したデータを返すpopメソッド、およびスタックに格納されているデータ数を返すsizeメソッドがあるとします。</p>
<p>リスト2は、Stackクラスを使ったプログラムの例です。</p>
<p>ここでは、stackという名前のスタックを生成し、スタックに&#8221;A&#8221;と&#8221;B&#8221;というデータを格納して、スタックからすべてのデータを取り出して表示しています。スタックは、LIFO形式なので、&#8221;B&#8221;、&#8221;A&#8221;の順に表示されます。</p>
<p><span class="chip">リスト2　Stackクラスを使ったプログラムの例<i class="material-icons blue-text mag_w05">code</i></span></p>
<pre>
    <code>
// スタックを生成する
Stack:stack ← Stack()

// スタックにデータを格納する
stack.push("A")
stack.push("B")

// スタックからすべてのデータを取り出す
while (stack.size() ＞ 0)
  stack.pop()の戻り値を表示する
endwhile
    </code>
</pre>
<h2>基本情報技術者試験の問題にチャレンジ</h2>
<p>試験対策として、2022年12月に公開された科目Bサンプル問題セットの問8にチャレンジしてみましょう。</p>
<p>これは、オブジェクトで実現したキューをテーマにした問題です。<br />このキューは、FIFO形式ですが、優先度付きであることに注意してください。<br />以下に問題を示します。</p>
<div class="card-panel mag_h30">
<p>次の記述中の<span class="blank"></span>に入れる正しい答えを、解答群の中から選べ。</p>
<p>優先度付きキューを操作するプログラムである。優先度付きキューとは扱う要素に優先度を付けたキューであり，要素を取り出す際には優先度の高いものから順番に取り出される。クラス PrioQueue は優先度付きキューを表すクラスである。クラス PrioQueue の説明を図に示す。ここで，優先度は整数型の値1，2，3のいずれかであり，小さい値ほど優先度が高いものとする。</p>
<p>手続 prioSched を呼び出したとき，出力は<span class="blank"></span>の順となる。</p>
<figure>
<div class="material-placeholder center"><img src="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/wp-content/uploads/2023/10/da9c8fe340571bb3c3001d536a63234d-1.jpg" alt="" style="max-width: 600px;"></div>
</figure>
<p><span class="chip">プログラム<i class="material-icons blue-text mag_w05">code</i></span></p>
<pre>
    <code>
○prioSched()   
    PrioQueue: prioQueue ← PrioQueue()
    prioQueue.enqueue("A", 1)
    prioQueue.enqueue("B", 2)
    prioQueue.enqueue("C", 2)
    prioQueue.enqueue("D", 3)
    prioQueue.dequeue()  /* 戻り値は使用しない */
    prioQueue.dequeue()  /* 戻り値は使用しない */
    prioQueue.enqueue("D", 3)
    prioQueue.enqueue("B", 2)
    prioQueue.dequeue()  /* 戻り値は使用しない */
    prioQueue.dequeue()  /* 戻り値は使用しない */
    prioQueue.enqueue("C", 2)
    prioQueue.enqueue("A", 1)
    while (prioQueue.size() が 0 と等しくない)
        prioQueue.dequeue() の戻り値を出力
    endwhile
    </code>
</pre>
<p>解答群</p>
<p>ア “A”，“B”，“C”，“D” <br />
イ “A”，“B”，“D”，“D” <br />
ウ “A”，“C”，“C”，“D”<br />
エ “A”，“C”，“D”，“D”</p>
</div>
<p>dequeueメソッドで、キューから要素を取り出すときは、キュー内で最も優先度の高い要素が取り出されます。最も優先度の高い要素が複数ある場合は、それらのうち最初に格納された要素が取り出されます。</p>
<p>手続prioSchedで行われているキューへの格納と取り出しによって、キューの内容は以下のように変化します。ここでは、キューの1つの要素を<code>[文字列データ, 優先度]</code>で示しています。優先度は、値が小さいほど高いとされます。</p>
<pre>
    <code>
prioQueue.enqueue("A", 1)	[A, 1]
prioQueue.enqueue("B", 2)	[A, 1][B, 2]
prioQueue.enqueue("C", 2)	[A, 1][B, 2][C, 2]
prioQueue.enqueue("D", 3)	[A, 1][B, 2][C, 2][D, 3]
prioQueue.dequeue() 		[B, 2][C, 2][D, 3]
prioQueue.dequeue()		[C, 2][D, 3]
prioQueue.enqueue("D", 3)	[C, 2][D, 3][D, 3]
prioQueue.enqueue("B", 2)	[C, 2][D, 3][D, 3][B, 2]
prioQueue.dequeue()		[D, 3][D, 3][B, 2]
prioQueue.dequeue()		[D, 3][D, 3]
prioQueue.enqueue("C", 2)	[D, 3][D, 3][C, 2]
prioQueue.enqueue("A", 1)	[D, 3][D, 3][C, 2][A, 1]
    </code>
</pre>
<p>キューの内容が<code>[D, 3][D, 3][C, 2][A, 1]</code>となった後で、while文を使ってキューの要素数が0になるまで、キューからデータの取り出しと出力（何に出力するかは示されていませんが、画面に出力すれば表示されます）を繰り返しています。<br /><code>[D, 3][D, 3][C, 2][A, 1]</code>からは、<code>[A, 1]、[C, 2]</code>、前側の<code>[D, 3]</code>、後側の<code>[D, 3]</code>の順に取り出されるので、出力はA、C、D、Dの順になります。</p>
<p>したがって、選択肢エが正解です。</p>
<div class="divider mag_tp50 mag_bt30"></div>
<p>今回は、キューとスタックを取り上げました。<br />次回も、シラバスに示されたアルゴリズムとデータ構造を解説します。</p>
<p>それでは、またお会いしましょう！</p><p>The post <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/queueandstack/">比べてわかるキューとスタックの仕組み｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</a> first appeared on <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi">基本情報技術者試験 受験ナビ｜科目A・科目B対策から過去問解説まで 250本以上の記事を掲載</a>.</p>]]></content:encoded>
			</item>
		<item>
		<title>「リスト」というデータ構造｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</title>
		<link>https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/list/</link>
		<pubDate>Fri, 08 Sep 2023 10:40:03 +0000</pubDate>
		<dc:creator><![CDATA[矢沢 久雄]]></dc:creator>
				<category><![CDATA[アルゴリズム]]></category>
		<category><![CDATA[科目 B]]></category>
		<category><![CDATA[過去問演習]]></category>

		<guid isPermaLink="false">https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/?post_type=similar_programming&#038;p=8011</guid>
		<description><![CDATA[<p>基本情報技術者試験は、2023年4月から新制度で実施されています。 この連載では、新制度の擬似言語（旧制度の擬似言語とは、表記方法に違いがあります）を使って、試験のシラバス（情報処理技術者試験における知識・技能の細目）に [&#8230;]</p>
<p>The post <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/list/">「リスト」というデータ構造｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</a> first appeared on <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi">基本情報技術者試験 受験ナビ｜科目A・科目B対策から過去問解説まで 250本以上の記事を掲載</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>基本情報技術者試験は、2023年4月から新制度で実施されています。</p>
<p>この連載では、新制度の擬似言語（旧制度の擬似言語とは、表記方法に違いがあります）を使って、試験のシラバス（情報処理技術者試験における知識・技能の細目）に示されている代表的なアルゴリズムとデータ構造を、プログラミング入門者向けにやさしく解説します。受験対策としてだけでなく、アルゴリズムとプログラミングの基礎知識を習得するために、ぜひお読みください。</p>
<style>pre{background:#263238!important;border-radius:unset;}pre:not([class*="language-"]){font-family:'consolas','Courier New',"HCo Gotham SSm",Gotham,"ヒラギノ角ゴ Pro W3","Hiragino Kaku Gothic ProN","Hiragino Sans","BIZ UDPGothic",Meiryo,sans-serif!important;color:#ccc;font-size:1em;padding:1em;}ol.background{padding-left:3em!important;}@media only screen and (max-width:600px){ol{padding-left:1em}dd{margin-left:2em}}</style>
<p>今回は、「<span class="bold">リスト</span>」というデータ構造を取り上げます。</p>
<h2>リストとは？</h2>
<p>試験のシラバスには、代表的なデータ構造として、配列、リスト、キュー、スタック、二分探索木、ヒープなどが示されていますが、どのデータ構造も、その実体は配列です。他のデータ構造は、配列の使い方にプログラムで様々な工夫を加えることで実現されています。<br />今回のテーマであるリスト（連結リストとも呼びます）は、配列の個々の要素が次の要素へのつながり情報を持ったものです。このつながり情報のことをポインタとも呼びます。次の要素を指し示す（ポイントする）ものだからです。</p>
<p>配列（リストではない通常の配列）とリストの違いを説明しましょう。</p>
<p>例として、東海道新幹線の東京から新大阪まで、のぞみ号が停車する駅名を、配列とリストで表してみます。<br />配列の場合は、要素番号（先頭の要素番号を1とします）の順に要素をたどるので、東京から新大阪までの駅名を要素番号の順に格納します（図1）。</p>
<figure><figcaption>図1　配列は、要素番号の順に要素をたどる</figcaption><div class="material-placeholder"><img src="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/wp-content/uploads/2023/09/795316b92fc766b0181f6fef074f03fa.jpg" alt=""></div>
</figure>
<p>「品川がない」と気づかれたと思いますが、後の説明の都合で入れていません。<br />リストの場合は、個々の要素が持つつながり情報（次の要素の要素番号やアドレス）で要素をたどるので、要素の格納順は任意で構いません（図2）。</p>
<figure><figcaption>図2　リストは、つながり情報で要素をたどる（ここでは先頭の要素をa[1]とする）</figcaption><div class="material-placeholder"><img src="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/wp-content/uploads/2023/09/2b530e80c7d0de90885e285c5d798063.jpg" alt=""></div>
</figure>
<p>配列と比べて、リストには、要素の挿入が効率的にできるという長所があります。</p>
<p>先ほど図1と図2に示した例に、品川を挿入してみましょう。</p>
<p><span class="bold">配列</span>の場合は以下の手順です（図3）</p>
<ol>
<li>新横浜以降の要素を1つずつ後ろにずらす</li>
<li>a[2] の位置に品川を挿入</li>
</ol>
<p>※要素をずらす処理に時間がかかります。</p>
<figure><figcaption>図3　配列への要素の挿入は、要素をずらす処理が必要である</figcaption><div class="material-placeholder"><img src="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/wp-content/uploads/2023/09/c8856789ec11ab8b1013037cef6929f9.jpg" alt=""></div>
</figure>
<p><span class="bold">リスト</span>の場合は以下の手順です（図4）</p>
<ol>
<li>配列の末尾のa[6]に品川を追加</li>
<li>東京の「次は4」を「次は6」に更新</li>
<li>品川に「次は4」を設定</li>
</ol>
<figure><figcaption>図4　リストへの要素の挿入では、要素をずらす処理が不要である</figcaption><div class="material-placeholder"><img src="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/wp-content/uploads/2023/09/3a4f695a458cb0ac0aceaa2eb13ac2dd.jpg" alt=""></div>
</figure>
<p>これだけで、東京と新横浜の間に品川を挿入できます。要素をずらす処理が不要なので時間がかかりません。<br />リストでは、要素の削除も、つながり情報の更新だけで済むので、配列より効率的です。</p>
<h2>リストをプログラムで実現する方法</h2>
<p>リストをプログラムで実現するには、データの値とつながり情報を要素とした配列を定義します。基本情報技術者試験のサンプル問題や公開問題では、これをクラスとして実現しています。クラスは、オブジェクトの定義であり、複数のデータと複数の処理をまとめたモジュール（プログラムの部品）です。</p>
<p>ここでは、駅のリストの要素を表すStationクラスを定義することにします。<br />擬似言語では、クラスが持つデータをメンバ変数と呼び、クラスが持つ処理をメソッドと呼びます。<br />Stationクラスには、駅名を示すメンバ変数name、次の要素のアドレスを格納するメンバ変数next、および新たな要素を作成するコンストラクタStationがあるとします。コンストラクタは、特殊なメソッドであり、クラス名と同名のメソッドにします。これまでの例では、要素番号をつながり情報としていましたが、ここでは、メモリ上に要素を新たに作成していくので、要素のメモリアドレスをつながり情報とします。</p>
<h3>まず、品川なしで、東京→新横浜→名古屋→京都→新大阪というリストを作成しましょう。</h3>
<p>以下にプログラムを示します。</p>
<p><span class="chip">プログラム<i class="material-icons blue-text mag_w05">code</i></span></p>
<pre>
    <code>
Station：listHead		// リストの先頭の要素のアドレスを格納する変数
Station：cur			// 現在の処理対象の要素のアドレス格納する変数
Station：temp			// 一時的にアドレスを格納する変数（後で使います）

cur ← Station("東京")		// 東京の要素を作成し処理対象とする
listHead ← cur			// 先頭の要素を東京とする

cur.next ← Station("新横浜")	// 新横浜の要素を作成し東京の次とする
cur ← cur.next			// 新横浜を処理対象とする

cur.next ← Station("名古屋")	// 名古屋の要素を作成し新横浜の次とする
cur ← cur.next			// 名古屋を処理対象とする

cur.next ← Station("京都")	// 京都の要素を作成し名古屋の次とする
cur ← cur.next			// 京都を処理対象とする

cur.next ← Station("新大阪")	// 新大阪の要素を作成し京都の次とする
cur ← cur.next			// 新大阪を処理対象とする
cur.next ← 未定義の値		// 新大阪の次を無し（未定義の値）とする
    </code>
</pre>
<p>要素のアドレスを格納する変数のデータ型は、Stationクラスにします。<br />変数listHeadには、リストの先頭の要素のアドレスを格納します。<br />変数cur（current＝「現在の」という意味です）には、現在の処理対象となっている要素のアドレスを格納します。<br />個々の要素が持つメンバ変数は「要素名.メンバ変数名」という構文で指定します。<br />cur.nextは、次の要素のアドレス（つながり情報）を示します。<br />cur ← cur.nextは、現在の次の要素を、新たな処理対象にします</p>
<h3>次に、東京と新横浜の間に品川を挿入してみましょう。</h3>
<p>lishHeadから、つながり情報で要素をたどり、駅名が東京なら、その要素と次の要素の間に品川を挿入します。<br />コメントを参考にしながら、以下のプログラム（先ほどのプログラムの続きだとします）を読み取ってください。</p>
<p><span class="chip">プログラム<i class="material-icons blue-text mag_w05">code</i></span></p>
<pre>
    <code>
cur ← listHead			// リストの先頭の要素を処理対象とする

while (cur.next ≠ 未定義の値)	// 末尾の要素まで繰り返す
    if (cur.name ＝ "東京")	// 現在の要素が東京なら品川を挿入する
        temp ← cur.next	// 東京の次のアドレスをtempに逃がしておく
        cur.next ← Station("品川")  // 品川の要素を作成し東京の次とする
        cur ← cur.next		// 品川を処理対象とする
        cur.next ← temp	// 逃がしておいたアドレスを品川の次に設定する
        繰り返し処理を抜ける	// 繰り返しを抜ける
    endif
   cur ← cur.next		// 次の要素を処理対象とする
endwhile
    </code>
</pre>
<p>ここでは、繰り返し処理を抜ける処理を「繰り返し処理を抜ける」という日本語の文章で示しています。サンプル問題や公開問題でも、同様の表現が使われているからです。</p>
<h2>基本情報技術者試験の公開問題にチャレンジ</h2>
<p>最後に、試験対策として、2022年4月に公開（8月に一部改訂）された科目Bサンプル問題の問3にチャレンジしてみましょう。</p>
<p>これは、リストへの要素の追加をテーマにした問題です。<br />リストに要素を追加する手続appendの処理内容を読み取ってください。問題文の中にある「インスタンスの参照」とは、要素のアドレスという意味です。</p>
<p>問３　次のプログラムの中の［　a　］と［　b　］に入れる正しい答えの組み合わせを、解答群の中から選べ。</p>
<p>手続 append は，引数で与えられた文字を単方向リストに追加する手続である。単方向リストの各要素は，クラス ListElement を用いて表現する。クラス ListElement の説明を図に示す。ListElement 型の変数はクラス ListElement のインスタンスの参照を格納するものとする。大域変数 listHead は，単方向リストの先頭の要素の参照を格納する。リストが空のときは，listHead は未定義である。</p>
<figure>
<div class="material-placeholder"><img src="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/wp-content/uploads/2023/09/64f935f1d6b8b3325f658c4707a0f89b.jpg" alt=""></div>
</figure>
<figure>
<div class="material-placeholder"><img src="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/wp-content/uploads/2023/09/ca2f824df775b84289ad638b8c259e76.jpg" alt=""></div>
</figure>
<figure>
<div class="material-placeholder"><img src="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/wp-content/uploads/2023/09/47c3053f67315545e7f21934c0e012da.jpg" alt=""></div>
</figure>
<p>大域変数（プログラムのどこからでも利用できる変数）listHeadには、初期値として、未定義の値が格納されています。これは、リストが空の状態であるということです。</p>
<p>手続appendは、引数qValの値を持つ要素をリストに追加します。<br />appendの最初の処理として、引数qValを格納した要素を新たに作成し、そのアドレスを変数currに格納しています。<br />次に、もしもlistHeadの値が空欄aなら、大域変数listHeadに変数currを代入しています。これは、新たに作成した要素をリストの先頭にする処理なので、最初の要素を挿入する場合です。listHeadの値が未定義の値なら、最初の要素だと判断できるので、空欄aは、未定義の値です。これで、正解を解答群の選択肢ア、イ、ウに絞り込めました。</p>
<p><p>空欄bがあるelseブロックは、最初の要素でない場合の処理なので、リストの末尾の要素の次に、新たに作成した要素を追加します。<br />そのために、変数prev（previous＝「前の」という意味です）に大域変数listHeadの値を格納し、「prev.nextが未定義でない」という条件のwhileブロックで繰り返し処理を行います。この処理では、変数prevにprev.nextを格納して、リストをたどっています。これが「prev.nextが未定義でない」という条件が真である限り繰り返されるので、繰り返しを抜けたときには、変数prevに既存のリストの末尾の要素のアドレスが得られます。<br />その要素の次を意味するメンバ変数prev.nextに、新たに作成した要素のアドレスを格納すれば、リストに要素を追加できるので、空欄bはcurrです。<br />以上のことから、選択肢アが正解です。</p>
<p>解答：ア</p>
<p style="margin:3rem auto;">☆　　　☆　　　☆</p>
<p>今回は、リストを取り上げました。<br />次回以降も、シラバスに示されたアルゴリズムとデータ構造を学んでいきます。</p>
<p><p>それでは、またお会いしましょう！</p><p>The post <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/list/">「リスト」というデータ構造｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</a> first appeared on <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi">基本情報技術者試験 受験ナビ｜科目A・科目B対策から過去問解説まで 250本以上の記事を掲載</a>.</p>]]></content:encoded>
			</item>
		<item>
		<title>サーチのアルゴリズム (3) ハッシュ表探索法のアルゴリズム｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</title>
		<link>https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/hash_table/</link>
		<pubDate>Thu, 03 Aug 2023 02:30:29 +0000</pubDate>
		<dc:creator><![CDATA[矢沢 久雄]]></dc:creator>
				<category><![CDATA[アルゴリズム]]></category>
		<category><![CDATA[科目 B]]></category>
		<category><![CDATA[過去問演習]]></category>

		<guid isPermaLink="false">https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/?post_type=similar_programming&#038;p=7978</guid>
		<description><![CDATA[<p>基本情報技術者試験は、 2023 年 4 月から新制度で実施されています。 この連載では、新制度で採用された新しい擬似言語（旧制度の擬似言語とは、表記方法に違いがあります）を使って、試験のシラバス（情報処理技術者試験にお [&#8230;]</p>
<p>The post <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/hash_table/">サーチのアルゴリズム (3) ハッシュ表探索法のアルゴリズム｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</a> first appeared on <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi">基本情報技術者試験 受験ナビ｜科目A・科目B対策から過去問解説まで 250本以上の記事を掲載</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>基本情報技術者試験は、 2023 年 4 月から新制度で実施されています。</p>
<p>この連載では、新制度で採用された新しい擬似言語（旧制度の擬似言語とは、表記方法に違いがあります）を使って、試験のシラバス（情報処理技術者試験における知識・技能の細目）に示されている代表的なアルゴリズムとデータ構造を、プログラミング入門者向けにやさしく解説します。 受験対策としてだけでなく、アルゴリズムとプログラミングの基礎知識を習得するために、ぜひお読みください。</p>
<p>今回は、サーチのアルゴリズムの 3 つめとして「<span class="bold">ハッシュ表探索法</span>」を取り上げます。</p>
<div class="divider mag_tp40 mag_bt10"></div>
<p class="grey-text small-text"><i class="material-icons mag_rt05">info_outline</i>他のサーチアルゴリズムの記事</p>
<blockquote><p><a href="../sequential_search/">サーチのアルゴリズム (1) 線形探索法</a><br /><a href="../binary_search/">サーチのアルゴリズム (2) 二分探索法</a></p></blockquote>
<div class="divider mag_bt40 mag_tp10"></div>
<style>article,pre,code{font-family:'consolas','Courier New',"HCo Gotham SSm",Gotham,"ヒラギノ角ゴ Pro W3","Hiragino Kaku Gothic ProN","Hiragino Sans","BIZ UDPGothic",Meiryo,sans-serif!important;}pre,code{background:#263238;color:#eceff1;border-radius:unset;font-size:1em;line-height:1.8;position:relative;}pre{margin:auto -7.5%;padding:1em 7.5%;}.card-panel pre{margin:1em -24px}code{padding:.15em .25em;}.card-panel{box-shadow:0 4px 16px rgba(0,0,0,0.02),0 20px 46px rgba(0,0,0,0.08);}.mini-chip{font-size:12px;padding:4px 7px;border-radius:50%;vertical-align:middle;background:#00bcd4;color:white;}</style>
<h2>計算量が O(1) になる理由</h2>
<h3>計算量を表すオーダー表記</h3>
<p><span class="u">アルゴリズムの良し悪しを示す尺度として「<span class="bold">計算量</span>」</span>というものがあります。</p>
<p>計算量には、いくつかの表記方法がありますが、よく使われるのは「オーダー表記」と呼ばれるものです。 これは、データ数の増加に対して処理回数がどのように増えるかを「 O( n の式) 」<br />
という表記で示したものです。この O は、 order （次数、規模）の頭文字です。</p>
<p>&nbsp;</p>
<p>たとえば、単純なループ（一重のループ）を使う線形探索法の計算量は、</p>
<pre>O(n)</pre>
<p>です。 n の 1 次式なので、線形探索法の処理回数は、データが 10 倍になれば 10 倍になり、 100 倍になれば 100 倍になります。</p>
<p>多重ループ（二重のループ）を使うバブルソートの計算量は、</p>
<pre>O(n<sup>2</sup>)</pre>
<p>です。 n の 2 次式なので、バブルソートの処理回数は、データが 10 倍になれば 100 倍になり、 100 倍になれば 10000 倍になります。</p>
<h3>ハッシュ表探索法の計算量</h3>
<p>それでは、今回のテーマであるハッシュ表探索法の計算量はいくつなのかというと、理想的には</p>
<pre>O(1)</pre>
<p>です。</p>
<p>この 1 は、ハッシュ表探索法の処理回数は、<span class="u">データ数に関わらず 1 回であることを意味</span>しています。 「理想的には」と但し書きを入れているのは、 1 回より多くなる場合もあり得るからです。それに関しては、後で説明します。</p>
<p>&nbsp;</p>
<p>ハッシュ表探索法では、データの値からデータの格納場所を決める「<span class="bold">ハッシュ関数</span>」を用意しておきます。</p>
<p>たとえば、要素数 10 個の配列 a[1] ～ a[10] （後でチャレンジする公開問題に合わせて、配列の要素番号は 1 から始まるとします）に、正の整数データを格納するなら、</p>
<pre>データの値 mod 10 + 1</pre>
<p>というハッシュ関数を用意し、このハッシュ関数で得られた値（「<span class="bold">ハッシュ値</span>」と呼びます）をデータの格納場所にします。 <code>データの値 mod 10 + 1</code> で得られる値は 1 ～ 10 になるので、格納場所は配列 a[1] ～ a[10] の範囲に収まります。</p>
<p>&nbsp;</p>
<p>たとえば、 45 というデータは、</p>
<pre>45 mod 10 + 1 = 6</pre>
<p>なので a[6] に格納します。</p>
<p>78 というデータは、</p>
<pre>78 mod 10 + 1 = 9</pre>
<p>なので a[9] に格納します。</p>
<p>このようにしてデータを格納した表を「<span class="bold">ハッシュ表</span>」と呼び、ハッシュ表を使った探索を「<span class="bold">ハッシュ表探索法</span>」と呼ぶのです。 ハッシュ（ hash ）は、「切り刻む」や「ごった混ぜにする」という意味です。</p>
<p>&nbsp;</p>
<p>このハッシュ表から、たとえば 45 というデータを探索するには、</p>
<pre>45 mod 10 + 1 = 6</pre>
<p>なので a[6] をチェックします。 a[6] には 45 が格納されているので 1 回の処理で見つかります。</p>
<p>同様に、 78 というデータを探索するには、</p>
<pre>78 mod 10 + 1 = 9</pre>
<p>なので a[9] をチェックして 1 回の処理で見つかります。 これが、ハッシュ表探索法で計算量が</p>
<pre>O(1)</pre>
<p>になる理由です。</p>
<p>なお、データが格納されていない要素には、それがわかるように、通常のデータではないことを意味する値を入れておきます。 ここでは、データが正の整数なので、 0 や -1 などを入れておけばよいでしょう（図 1 ）。</p>
<figure class="responsive-width"><figcaption>図 1　ハッシュ表探索法の仕組み</figcaption><img class="materialboxed z-depth-5" src="../../wp-content/uploads/2023/08/hash_table.jpg" loading="lazy"><br />
</figure>
<h2>シノニムに対処する方法</h2>
<p>ハッシュ表探索法の計算量は、理想的に <code>O(1)</code> です。 ここで、理想的というのは、ハッシュ表に格納するデータ群の中に、同じハッシュ値になるデータ（これを「<span class="bold">シノニム</span>（ synonym = 同義語、類義語）」と呼びます）がない場合です。</p>
<p>もしも、シノニムがあると、それに対処するための処理が必要になり、 1 回ではデータが見つかりません。</p>
<p>&nbsp;</p>
<p>たとえば、先ほど図 1 の <span class="mini-chip">3</span> に示したハッシュ表に、 95 を格納するとしましょう。 95 のハッシュ値は、</p>
<pre>95 mod 10 + 1 = 6</pre>
<p>であり、すでに a[6] に格納されている 45 と同じになります。 95 はシノニムであり、ハッシュ値の a[6] に格納できません。</p>
<p>&nbsp;</p>
<p>シノニムに対処する方法は、いくつか考えられますが、単純な方法は、ハッシュ値で得た格納場所より先（末尾を超えた場合は先頭に戻る）で最初に空いている場所に格納する方法です。</p>
<p>ここでは、 a[6] より先で最初に空いている（ -1 が格納されている）のが a[7] なので、そこに 95 を格納します。 この場合には、 95 は 1 回では見つかりません（図 2 ）。</p>
<figure class="responsive-width"><figcaption>図 2　シノニムのデータは 1 回では見つからない</figcaption><img class="materialboxed z-depth-5" src="../../wp-content/uploads/2023/08/synonym.jpg" loading="lazy"><br />
</figure>
<h2>基本情報技術者試験の公開問題にチャレンジ</h2>
<p>最後に、試験対策として<a href="https://www.ipa.go.jp/shiken/mondai-kaiotu/sg_fe/koukai/t6hhco0000003zx0-att/2023r05_fe_kamoku_b_qs.pdf#page=8" rel="noopener" target="_blank">「令和 5 年度 基本情報技術者試験 科目 B 公開問題」</a>の問 4 にチャレンジしてみましょう。</p>
<p>ハッシュ表探索をテーマにした問題であり、シノニムの対処もあります。</p>
<div class="card-panel mag_h30">
<p class="bold">問 4</p>
<p>　次の記述中の<span class="blank"></span>に入れる正しい答えを，解答群の中から選べ。ここで，配列の要素番号は 1 から始まる。</p>
<p>　関数 add は，引数で指定された正の整数 value を大域の整数型の配列 hashArray に格納する。格納できた場合は true を返し，格納できなかった場合は false を返す。<br />
ここで，整数 value を hashArray のどの要素に格納すべきかを，関数 calcHash1 及び calcHash2 を利用して決める。</p>
<p>　手続 test は，関数 add を呼び出して，hashArray に正の整数を格納する。手続 test の処理が終了した直後の hashArray の内容は，<span class="blank"></span>である。</p>
<p><span class="chip">プログラム<i class="material-icons blue-text mag_w05">code</i></span></p>
<pre>
大域: 整数型の配列: hashArray

○論理型: add(整数型: value)
 整数型: i ← calcHash1(value)
 if (hashArray[i] = -1)
 hashArray[i] ← value
 return true
 else
 i ← calcHash2(value)
 if (hashArray[i] = -1)
 hashArray[i] ← value
 return true
 endif
 endif
 return false

○整数型: calcHash1(整数型: value)
 return (value mod hashArrayの要素数) + 1

○整数型: calcHash2(整数型: value)
 return ((value + 3) mod hashArrayの要素数) + 1

○test()
 hashArray ← {5 個の -1}
 add(3)
 add(18)
 add(11)</pre>
<p>解答群<br />
ア {-1, 3, -1, 18, 11}<br />
イ {-1, 11, -1, 3, -1}<br />
ウ {-1, 11, -1, 18, -1}<br />
エ {-1, 18, -1, 3, 11}<br />
オ {-1, 18, 11, 3, -1}
</p></div>
<p>プログラムの内容を説明しましょう。</p>
<p>ここでは、要素数 5 個の整数型の配列 hashArray がハッシュ表であり、そこに正の整数 value を格納します。</p>
<ul class="background c-round">
<li>hashArray のすべての要素には、初期値として、データが格納されていないことを意味する -1 が格納されています</li>
<li>関数 test では、引数 value の値を 3 、 18 、 11 として、ハッシュ表にデータを格納する関数 add を 3 回呼び出しています</li>
<li>ハッシュ関数は、 2 つ用意されています
<ul>
<li>関数 calcHash1 は <code>value mod 5 + 1</code> という計算でハッシュ値を得ます</li>
<li>関数 calcHash2 は <code>(value + 3) mod 5 + 1</code> という計算でハッシュ値を得ます</li>
</ul>
</li>
<li>関数 add は、関数 calcHash1 で得た場所が空いているなら、そこに value を格納して true を返し、空いていないなら、関数 calcHash2 で得た場所が空いているなら、そこに value を格納して true を返し、そこも空いていないなら、 false を返します。<br />関数 add の戻り値は、データを格納できたら true であり、格納できなかったら false です</li>
</ul>
<p>擬似言語の表記で示すと、初期状態のハッシュ表の内容は</p>
<pre>{-1, -1, -1, -1, -1}</pre>
<p>です。</p>
<p>最初の 3 は、関数 calcHash1 で得た</p>
<pre>3 mod 5 + 1 = 4</pre>
<p>の場所が空いてるので、そこに格納され、ハッシュ表の内容は</p>
<pre>{-1, -1, -1, 3, -1}</pre>
<p>になります。</p>
<p>次の 18 は、関数 calcHash1 で得た <code>18 mod 5 + 1 = 4</code> の場所が空いていないので、そこには格納せず、関数 calcHash2 で得た</p>
<pre>(18 + 3) mod 5 + 1 = 2</pre>
<p>の場所が空いてるので、そこに格納され、ハッシュ表の内容は</p>
<pre>{-1, 18, -1, 3, -1}</pre>
<p>になります。</p>
<p>最後の 11 は、関数 calcHash1 で得た <code>11 mod 5 + 1 = 2</code> の場所が空いていないので、そこには格納せず、関数 calcHash2 で得た</p>
<pre>(11 + 3) mod 5 + 1 = 5</pre>
<p>の場所が空いてるので、そこに格納され、ハッシュ表の内容は</p>
<pre>{-1, 18, -1, 3, 11}</pre>
<p>になります。</p>
<p>&nbsp;</p>
<p>以上のことから、選択肢エが正解です。</p>
<div class="divider mag_tp50 mag_bt30"></div>
<p>今回は、ハッシュ表探索法を取り上げました。</p>
<p>次回以降も、シラバスに示されたアルゴリズムとデータ構造を学んでいきます。</p>
<p>それでは、またお会いしましょう！</p><p>The post <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/hash_table/">サーチのアルゴリズム (3) ハッシュ表探索法のアルゴリズム｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</a> first appeared on <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi">基本情報技術者試験 受験ナビ｜科目A・科目B対策から過去問解説まで 250本以上の記事を掲載</a>.</p>]]></content:encoded>
			</item>
		<item>
		<title>クイックソートのアルゴリズム｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</title>
		<link>https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/quick_sort/</link>
		<pubDate>Tue, 18 Jul 2023 23:30:27 +0000</pubDate>
		<dc:creator><![CDATA[矢沢 久雄]]></dc:creator>
				<category><![CDATA[アルゴリズム]]></category>
		<category><![CDATA[科目 B]]></category>
		<category><![CDATA[過去問演習]]></category>

		<guid isPermaLink="false">https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/?post_type=similar_programming&#038;p=7907</guid>
		<description><![CDATA[<p>基本情報技術者試験は、 2023 年 4 月から新制度で実施されています。 この連載では、新制度で採用された新しい擬似言語（旧制度の擬似言語とは、表記方法に違いがあります）を使って、試験のシラバス（情報処理技術者試験にお [&#8230;]</p>
<p>The post <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/quick_sort/">クイックソートのアルゴリズム｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</a> first appeared on <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi">基本情報技術者試験 受験ナビ｜科目A・科目B対策から過去問解説まで 250本以上の記事を掲載</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>基本情報技術者試験は、 2023 年 4 月から新制度で実施されています。</p>
<p>この連載では、新制度で採用された新しい擬似言語（旧制度の擬似言語とは、表記方法に違いがあります）を使って、試験のシラバス（情報処理技術者試験における知識・技能の細目）に示されている代表的なアルゴリズムとデータ構造を、プログラミング入門者向けにやさしく解説します。 受験対策としてだけでなく、アルゴリズムとプログラミングの基礎知識を習得するために、ぜひお読みください。</p>
<p>前回は <a href="../recursive/">再帰呼び出し</a> を取り上げました。 今回は、再帰呼び出しを使った <span class="bold">クイックソート</span> を取り上げます。</p>
<style>article,pre,code{font-family:'consolas','Courier New',"HCo Gotham SSm",Gotham,"ヒラギノ角ゴ Pro W3","Hiragino Kaku Gothic ProN","Hiragino Sans","BIZ UDPGothic",Meiryo,sans-serif!important;}pre,code{background:#263238;color:#eceff1;border-radius:unset;font-size:1em;line-height:1.8;position:relative;}pre{margin:auto -7.5%;padding:1em 7.5%;}.card-panel pre{margin:1em -24px}code{padding:.15em .25em;}.card-panel{box-shadow:0 4px 16px rgba(0,0,0,0.02),0 20px 46px rgba(0,0,0,0.08);}</style>
<h2>クイックソートのアルゴリズム</h2>
<p>クイックソートは、配列をソートするアルゴリズムの一種です。 クイックソートのアルゴリズムは以下です。</p>
<div class="background c-round" style="position:relative;"><i class="material-icons blue-text" style="position:absolute;top:1em;left:1em;">format_quote</i></p>
<div class="mag_lt10">配列の中から基準値を選び、残りの要素を基準値より小さいグループと大きいグループに分けることを、グループの要素数が 1 個になるまで（ 2 個以上である限り）繰り返す</div>
<p><i class="material-icons blue-text" style="position:absolute;bottom:1em;right:1em;transform:rotateX(180deg);">format_quote</i></div>
<p>グループ分けすることでソートの対象となる<span class="u">配列の要素数が徐々に少なくなること</span>と、プログラムで繰り返しを実現するときに<span class="u">再帰呼び出し</span>（関数や手続の処理の中で、同じ関数や手続を呼び出すことで、繰り返しを実現するプログラミング技法）を使うことが、クイックソートの特徴です。</p>
<p>&nbsp;</p>
<p>図 1 は、要素数 7 個の配列（要素番号は 1 から始まるとします）を昇順にクイックソートする手順の例を示したものです。</p>
<figure class="responsive-width"><figcaption>図 1　要素数 7 個の配列を昇順にクイックソートする手順の例</figcaption><img class="materialboxed z-depth-5" src="../../wp-content/uploads/2023/07/quick_sort_image_1.jpg" loading="lazy"><br />
</figure>
<p>ここでは、ソート対象となる配列の真ん中の要素を基準値としています。</p>
<p>真ん中の要素の要素番号は、</p>
<blockquote><p>(左端の要素の要素番号 + 右端の要素の要素番号) ÷ 2</p></blockquote>
<p>という計算で求められます。 要素番号は、整数型のデータなので、除算結果の小数点以下はカットされます。</p>
<p>初期状態（図 1 の【手順 1 】）では、ソート対象となる配列が a[1] ～ a[7] なので、</p>
<blockquote><p>(1 + 7) ÷ 2 = 4</p></blockquote>
<p>となり、 a[4] に格納されている 4 が基準値です。</p>
<figure class="responsive-width"><figcaption>図 1　要素数 7 個の配列を昇順にクイックソートする手順の例</figcaption><img class="materialboxed z-depth-5" src="../../wp-content/uploads/2023/07/quick_sort_image_2.jpg" loading="lazy"><br />
  <img class="materialboxed z-depth-5" src="../../wp-content/uploads/2023/07/quick_sort_image_3.jpg" loading="lazy"><br />
</figure>
<p>配列の先頭から基準値より大きい値を探索し、配列の末尾から基準値より小さい値を探索して、大きい値と小さい値を交換することを繰り返すと、基準値との大小関係で配列のグループ分けができます。</p>
<figure class="responsive-width"><figcaption>図 1　要素数 7 個の配列を昇順にクイックソートする手順の例</figcaption><img class="materialboxed z-depth-5" src="../../wp-content/uploads/2023/07/quick_sort_image_4.jpg" loading="lazy"><br />
  <img class="materialboxed z-depth-5" src="../../wp-content/uploads/2023/07/quick_sort_image_5.jpg" loading="lazy"><br />
</figure>
<p>同じ手順を、グループ分けしたそれぞれのグループで繰り返します。 グループの要素数が 1 個になったら繰り返しを終了します。 すべてのグループの繰り返しが終了したら、配列全体のソートが完了します。</p>
<h2>クイックソートのプログラム</h2>
<p>リスト 1 は、クイックソートのプログラムの例です。</p>
<p>これは、 2023 年 7 月 6 日に情報処理推進機構から公開された<a href="https://www.ipa.go.jp/shiken/mondai-kaiotu/sg_fe/koukai/t6hhco0000003zx0-att/2023r05_fe_kamoku_b_qs.pdf#page=6" rel="noopener" target="_blank">「令和 5 年度 基本情報技術者試験 科目 B 公開問題」</a>の問 3 に示されたプログラムに、若干のアレンジを加えたものです。</p>
<p>手続 sort は、配列を昇順にクイックソートします。<br />
引数 a は、ソート対象の配列です。<br />
引数 first は、ソート対象の先頭の要素番号です。<br />
引数 last は、ソート対象の末尾の要素番号です。<br />
配列の要素番号は、 1 から始まるとします。</p>
<p class="grey-text hide-on-med-and-up mag_h10 small-text"><i class="material-icons light-blue-text mag_rt05">swipe</i>プログラムは横スクロールできます</p>
<figure><figcaption class="chip" style="height:auto;">リスト 1<i class="material-icons blue-text mag_w05">code</i> クイックソートのプログラムの例</figcaption><pre>○<span class="yellow-text text-lighten-4">sort</span><span class="yellow-text">(</span><span class="blue-text">整数型の配列</span>: <span class="cyan-text text-lighten-3">a</span>, <span class="blue-text">整数型</span>: <span class="cyan-text text-lighten-3">first</span>, <span class="blue-text">整数型</span>: <span class="cyan-text text-lighten-3">last</span><span class="yellow-text">)</span>
  <span class="blue-text">整数型</span> <span class="cyan-text text-lighten-3">pivot</span>, <span class="cyan-text text-lighten-3">i</span>, <span class="cyan-text text-lighten-3">j</span>, <span class="cyan-text text-lighten-3">temp</span>

  <span class="grey-text">/* 配列の真ん中の要素を基準値とし
     基準値の要素番号を pivot に設定する */</span>
  <span class="cyan-text text-lighten-3">pivot</span> ← <span class="cyan-text text-lighten-3">a</span><span class="purple-text text-lighten-3">[</span><span class="yellow-text">(</span><span class="cyan-text text-lighten-3">first</span> + <span class="cyan-text text-lighten-3">last</span><span class="yellow-text">)</span> ÷ 2<span class="purple-text text-lighten-3">]</span>

  <span class="grey-text">/* 配列の先頭の要素番号を i に設定する */</span>
  <span class="cyan-text text-lighten-3">i</span> ← <span class="cyan-text text-lighten-3">first</span>

  <span class="grey-text">/* 配列の末尾の要素番号を j に設定する */</span>
  <span class="cyan-text text-lighten-3">j</span> ← <span class="cyan-text text-lighten-3">last</span>

  <span class="grey-text">/* 無限ループで繰り返す */</span>
  <span class="purple-text text-lighten-3">while</span> <span class="yellow-text">(</span>true<span class="yellow-text">)</span>
    <span class="grey-text">/* 配列の先頭から pivot 以上の要素を探索し、見つかった位置を i に得る */</span>
    <span class="purple-text text-lighten-3">while</span> <span class="yellow-text">(</span>a<span class="purple-text text-lighten-3">[</span>i<span class="purple-text text-lighten-3">]</span> &lt; <span class="cyan-text text-lighten-3">pivot</span><span class="yellow-text">)</span>
      <span class="cyan-text text-lighten-3">i</span> ← <span class="cyan-text text-lighten-3">i</span> + <span class="amber-text">1</span>
    <span class="purple-text text-lighten-3">endwhile</span>

    <span class="grey-text">/* 配列の末尾から pivot 以下の要素を探索し、見つかった位置を j に得る */</span>
    <span class="purple-text text-lighten-3">while</span> <span class="yellow-text">(</span><span class="cyan-text text-lighten-3">pivot</span> &lt; <span class="cyan-text text-lighten-3">a</span><span class="purple-text text-lighten-3">[</span>j<span class="purple-text text-lighten-3">]</span><span class="yellow-text">)</span>
      <span class="cyan-text text-lighten-3">j</span> ← <span class="cyan-text text-lighten-3">j</span> - <span class="amber-text">1</span>
    <span class="purple-text text-lighten-3">endwhile</span>

    <span class="grey-text">/* 探索の範囲を超えているなら */</span>
    <span class="purple-text text-lighten-3">if</span> <span class="yellow-text">(</span><span class="cyan-text text-lighten-3">i</span> ≧ <span class="cyan-text text-lighten-3">j</span><span class="yellow-text">)</span>
      <span class="grey-text">/* グループ分けが完了しているので無限ループを抜ける
         breakは、繰り返しを抜けるメールだとする */</span>
      <span class="purple-text text-lighten-3">break</span>
    <span class="purple-text text-lighten-3">endif</span>

    <span class="grey-text">/* 基準値の前側にある基準値以上の a[i] と
       基準値の後側にある基準値以下の a[j] を交換する*/</span>
    <span class="cyan-text text-lighten-3">temp</span> ← a<span class="purple-text text-lighten-3">[</span>i<span class="purple-text text-lighten-3">]</span>
    <span class="cyan-text text-lighten-3">a</span><span class="purple-text text-lighten-3">[</span>i<span class="purple-text text-lighten-3">]</span> ← <span class="cyan-text text-lighten-3">a</span><span class="purple-text text-lighten-3">[</span>j<span class="purple-text text-lighten-3">]</span>
    <span class="cyan-text text-lighten-3">a</span><span class="purple-text text-lighten-3">[</span>j<span class="purple-text text-lighten-3">]</span> ← <span class="cyan-text text-lighten-3">temp</span>
  <span class="purple-text text-lighten-3">endwhile</span>

  <span class="grey-text">/* グループ分けした前側の要素数が 2 個以上なら */</span>
  <span class="purple-text text-lighten-3">if</span> <span class="yellow-text">(</span><span class="cyan-text text-lighten-3">first</span> &lt; <span class="cyan-text text-lighten-3">i</span> - <span class="amber-text">1</span><span class="yellow-text">)</span>
    <span class="grey-text">/* 再帰呼び出しで、前側で同じ処理を繰り返す */</span>
    <span class="yellow-text text-lighten-4">sort</span><span class="yellow-text">(</span><span class="cyan-text text-lighten-3">a</span>, <span class="cyan-text text-lighten-3">first</span>, <span class="cyan-text text-lighten-3">i</span> - <span class="amber-text">1</span><span class="yellow-text">)</span>
  <span class="purple-text text-lighten-3">endif</span>

  <span class="grey-text">/* グループ分けした後側の要素数が 2 個以上なら */</span>
  <span class="purple-text text-lighten-3">if</span> <span class="yellow-text">(</span><span class="cyan-text text-lighten-3">j</span> + <span class="amber-text">1</span> &lt; <span class="cyan-text text-lighten-3">last</span><span class="yellow-text">)</span>
    <span class="grey-text">/* 再帰呼び出しで、後側で同じ処理を繰り返す */</span>
    <span class="yellow-text text-lighten-4">sort</span><span class="yellow-text">(</span><span class="cyan-text text-lighten-3">a</span>, <span class="cyan-text text-lighten-3">j</span> + <span class="amber-text">1</span>, <span class="cyan-text text-lighten-3">last</span><span class="yellow-text">)</span>
  <span class="purple-text text-lighten-3">endif</span></pre>
<p>プログラムに多くのコメントを入れてあります。 コメントを参考にして、プログラムの処理内容を読み取ってください。</p>
<p>注目してほしいのは、再帰呼び出しで繰り返しを行っている部分です。 手続 sort は、</p>
<blockquote><p>「基準値を決め、ソート対象の配列を基準値との大小関係でグループ分けする」</p></blockquote>
<p>という処理を行います。</p>
<p>この処理を、グループ分けされた前側と後側で繰り返すので、 <code><span class="yellow-text text-lighten-4">sort</span><span class="yellow-text">(</span> ソート対象の配列 <span class="yellow-text">)</span></code> の処理の中で、 <code><span class="yellow-text text-lighten-4">sort</span><span class="yellow-text">(</span> 前側のグループ <span class="yellow-text">)</span></code> と <code><span class="yellow-text text-lighten-4">sort</span><span class="yellow-text">(</span> 後側のグループ <span class="yellow-text">)</span></code> を呼び出すのです。 この部分が、再帰呼び出しです。</p>
<p>グループの要素数が 1 個になるまで（ 2 個以上である限り）、この再帰呼び出しを繰り返します。</p>
<h2>基本情報技術者試験の公開問題にチャレンジ</h2>
<p>最後に、試験対策として「令和 5 年度 基本情報技術者試験 科目 B 公開問題」の問 3 にチャレンジしてみましょう。</p>
<p>基本情報技術者試験の科目 B 試験では、 100 分で 20 問を解きます。 1 問当たりの解答時間の目安は、</p>
<blockquote><p>100 分 ÷ 20 問 = 5 分</p></blockquote>
<p>です。</p>
<p>この問題の中には「クイックソート」という言葉はありませんが、クイックソートのプログラムを学んだ経験があれば「あっ！ これはクイックソートだ」とすぐにわかり、 <span class="u">5 分程度ですんなり問題を解ける</span>でしょう。 逆に、クイックソートのプログラムを学習した経験がないと、<span class="u">相当な時間がかかるか、まったくお手上げでしょう</span>。</p>
<p>この問題から、試験対策として、シラバスに示されたアルゴリズムとデータ構造をきちんと学ぶことの重要性を感じてください。 <span class="u bold">「きちんと学ぶ」とは、単にアルゴリズムを理解するだけでなく、実際のプログラムでどのような処理になるのかを経験すること</span>です。</p>
<div class="card-panel mag_h30">
　次の記述中の<span class="blank"></span>に入れる正しい答えを，解答群の中から選べ。 ここで，配列の要素番号は 1 から始まる。</p>
<p>　次の手続 sort は，大域の整数型の配列 data の，引数 first で与えられた要素番号から引数 last で与えられた要素番号までの要素を昇順に整列する。ここで， first<br />
 &lt; last とする。 手続 sort を sort(1, 5) として呼び出すと， <span class="blue-text">/*** α ***/</span> の行を最初に実行したときの出力は &#8220;<span class="blank"></span>&#8221; となる。</p>
<p><span class="chip">プログラム<i class="material-icons blue-text mag_w05">code</i></span></p>
<pre>大域: 整数型の配列: data ← {2, 1, 3, 5, 4}

○sort(整数型: first, 整数型: last)
 整数型: pivot, i, j
 pivot ← data[(first + last) ÷ 2 の商]
 i ← first
 j ← last

 while (true)
  while (data[i] &lt; pivot)
    i ← i + 1
  endwhile
  while (pivot &lt; data[j])
    j ← j - 1
  endwhile
  if (i ≧ j)
    繰返し処理を終了する
  endif
  data[i] と data[j] の値を入れ替える
  i ← i + 1
  j ← j - 1
 endwhile
 data の全要素の値を要素番号の順に空白区切りで出力する <span class="blue-text">/*** α ***/</span>
 if (first &lt; i - 1)
   sort(first, i - 1)
 endif
 if (j + 1 &lt; last)
   sort(j + 1, last)
 endif</pre>
<p>解答群<br />
ア　1 2 3 4 5<br />
イ　1 2 3 5 4<br />
ウ　2 1 3 4 5<br />
エ　2 1 3 5 4
</p></div>
<p>先ほどリスト 1 に示したプログラムでは、ソート対象の配列を手続 sort の引数で指定していましたが、公開問題のプログラムでは、大域の配列（プログラムのどこからでも使える配列）としています。 これは、プログラムの内容をシンプルにするためでしょう。</p>
<p>このプログラムの処理内容は、リスト 1 に示したプログラムと同様です。 ここでは、</p>
<pre>data ← {2, 1, 3, 5, 4}</pre>
<p>という配列を最初にグループ分けした後で、 data の全要素の値を要素番号の順に空白区切りで出力した結果を、解答群の中から選びます。</p>
<p>最初のグループ分けでは、</p>
<pre>{2, 1, 3, 5, 4}</pre>
<p>の 3 を基準値として、配列全体をグループ分けします。</p>
<pre>{2, 1, 3, 5, 4}</pre>
<p>は、 3 の前に 3 より小さい値があり、 3 の後に 3 より大きい値があるので、要素の値の交換は行われず、このままでグループ分けが完了しています。</p>
<p>したがって、</p>
<pre>2 1 3 5 4</pre>
<p>と表示されます。 選択肢エが正解です。</p>
<div class="divider mag_tp50 mag_bt30"></div>
<p>今回は、クイックソート取り上げました。</p>
<p>次回以降も、シラバスに示されたアルゴリズムとデータ構造を学んでいきます。</p>
<p>それでは、またお会いしましょう！</p>
<div class="divider mag_tp40 mag_bt10"></div>
<p class="grey-text small-text"><i class="material-icons mag_rt05">info_outline</i>関連記事</p>
<p><a href="../../guide/comment_new_kakomon_202307/"></p>
<div class="row valign-wrapper pad_w20">
<div class="col s3 m2 flex pad_00"><img src="../../wp-content/uploads/2023/07/cover_comment_new_kakomon_202307-300x169.jpg" width="300" height="169" alt=" " loading="lazy"></div>
<div class="col s9 m10 pad_10 blue-grey-text bold">新制度・基本情報技術者試験の過去問（公開問題）からわかる難易度と対策</div>
</div>
<p></a></p><p>The post <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/quick_sort/">クイックソートのアルゴリズム｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</a> first appeared on <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi">基本情報技術者試験 受験ナビ｜科目A・科目B対策から過去問解説まで 250本以上の記事を掲載</a>.</p>]]></content:encoded>
			</item>
		<item>
		<title>再帰呼び出しのアルゴリズム｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</title>
		<link>https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/recursive/</link>
		<pubDate>Mon, 05 Jun 2023 23:30:17 +0000</pubDate>
		<dc:creator><![CDATA[矢沢 久雄]]></dc:creator>
				<category><![CDATA[アルゴリズム]]></category>
		<category><![CDATA[科目 B]]></category>

		<guid isPermaLink="false">https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/?post_type=similar_programming&#038;p=7830</guid>
		<description><![CDATA[<p>基本情報技術者試験は、 2023 年 4 月から新制度で実施されています。 この連載では、新制度で採用された新しい擬似言語（旧制度の擬似言語とは、表記方法に違いがあります）を使って、試験のシラバス（情報処理技術者試験にお [&#8230;]</p>
<p>The post <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/recursive/">再帰呼び出しのアルゴリズム｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</a> first appeared on <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi">基本情報技術者試験 受験ナビ｜科目A・科目B対策から過去問解説まで 250本以上の記事を掲載</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>基本情報技術者試験は、 2023 年 4 月から新制度で実施されています。</p>
<p>この連載では、新制度で採用された新しい擬似言語（旧制度の擬似言語とは、表記方法に違いがあります）を使って、試験のシラバス（情報処理技術者試験における知識・技能の細目）に示されている代表的なアルゴリズムとデータ構造を、プログラミング入門者向けにやさしく解説します。 受験対策としてだけでなく、アルゴリズムとプログラミングの基礎知識を習得するために、ぜひお読みください。</p>
<p>今回は <span class="bold">再帰呼び出し</span> を取り上げます。</p>
<style>article,pre,code{font-family:'consolas','Courier New',"HCo Gotham SSm",Gotham,"ヒラギノ角ゴ Pro W3","Hiragino Kaku Gothic ProN","Hiragino Sans","BIZ UDPGothic",Meiryo,sans-serif!important;}pre,code{background:#263238;color:#eceff1;border-radius:unset;font-size:1em;line-height:1.8;position:relative;}pre{margin:auto -7.5%;padding:1em 7.5%;}.card-panel pre{margin:1em -24px}code{padding:.15em .25em;}.card-panel{box-shadow:0 4px 16px rgba(0,0,0,0.02),0 20px 46px rgba(0,0,0,0.08);}</style>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@48,400,1,0" />
<h2>再帰呼び出しとは？</h2>
<p><span class="bold">再帰呼び出し</span>（ recursive call ）とは、「<span class="u">関数の処理の中で同じ関数を呼び出すことで繰り返しを実現する」</span>というプログラミング・テクニックです。</p>
<p>プログラムで繰り返しを実現するには、 while 文や for 文を使う方法がありますが、それらとは別に再帰呼び出しという方法もあるのです。</p>
<p>&nbsp;</p>
<p>再帰呼び出しの仕組みを説明するための代表的な例として、「引数で指定した数の階乗を返す関数」があります。 階乗とは、その数から 1 までのすべての数を掛けた値です。</p>
<p>たとえば、 5 の階乗は、<br />
5 × 4 × 3 × 2 × 1 = 120<br />
です。 数学の約束で、 <span class="u">0 の階乗は 1</span> と決められています。</p>
<p>リスト 1 は、引数 n （ 0 以上だとします）の階乗を返す factorial 関数の定義です。 factorial は、「階乗」という意味です。 factorial 関数の処理の中で同じ factorial 関数を呼び出していることに注目してください。 これが再帰呼び出しです。</p>
<p class="grey-text hide-on-med-and-up mag_h10 small-text"><i class="material-icons light-blue-text mag_rt05">swipe</i>プログラムは横スクロールできます</p>
<figure><figcaption class="chip" style="height:auto;">リスト 1<i class="material-icons blue-text mag_w05">code</i> 引数 n の階乗を返す factorial 関数の定義</figcaption><pre>○<span class="blue-text">整数型</span>: <span class="yellow-text text-lighten-4">factorial</span><span class="yellow-text">(</span><span class="blue-text">整数型</span>: <span class="cyan-text text-lighten-3">n</span><span class="yellow-text">)</span>
  <span class="purple-text text-lighten-3">if</span> <span class="yellow-text">(</span><span class="cyan-text text-lighten-3">n</span> = <span class="amber-text">0</span><span class="yellow-text">)</span>
    <span class="purple-text text-lighten-3">return</span> <span class="amber-text">1</span>
  <span class="purple-text text-lighten-3">else</span>
    <span class="purple-text text-lighten-3">return</span> <span class="cyan-text text-lighten-3">n</span> × <span class="yellow-text text-lighten-4">factorial</span><span class="yellow-text">(</span><span class="cyan-text text-lighten-3">n</span> - <span class="amber-text">1</span><span class="yellow-text">)</span> <span class="grey-text">// <span class="bold">これが再帰呼び出し</span></span>
  <span class="purple-text text-lighten-3">endif</span></pre>
<p>リスト 1 では、<br />
「 n の階乗は、 n × (n &#8211; 1) の階乗である」<br />
という考えで、階乗を求めています。 たとえば、 5 の階乗は、<br />
5 × 4 × 3 × 2 × 1<br />
ですが、これは<br />
5 × ( 4 の階乗)<br />
と考えることができます。</p>
<p>階乗を求める処理の中で、階乗を求める処理を使うことが、再帰呼び出しになるのです。</p>
<pre><span class="cyan-text text-lighten-3">n</span> × <span class="yellow-text text-lighten-4">factorial</span><span class="yellow-text">(</span><span class="cyan-text text-lighten-3">n</span> - <span class="amber-text">1</span><span class="yellow-text">)</span></pre>
<p>の部分は、<br />
「 n の階乗は、n × (n &#8211; 1) の階乗である」<br />
という考えをプログラムで表しています。</p>
<h3>再帰呼び出しの仕組み</h3>
<p>それでは、どうして再帰呼び出しで繰り返しが実現されるのでしょうか？ それは、関数を呼び出すと、関数の入り口から処理が行われるからです。</p>
<p>図 1 に示したように、 factorial 関数の処理の中で同じ factorial 関数を呼び出すと、 factorial 関数の処理が繰り返されます。</p>
<figure><figcaption>図 1　再帰呼び出しで繰り返しが実現される仕組み</figcaption><img class="materialboxed z-depth-5 responsive-width" src="../../wp-content/uploads/2023/06/recursive_image.jpg" loading="lazy"><br />
</figure>
<p>リスト 1 には、もう 1 つ注目してほしい部分があります。 それは、<span class="u">再帰呼び出しによる繰り返しが終わる部分</span>です。</p>
<pre>  <span class="purple-text text-lighten-3">if</span> <span class="yellow-text">(</span><span class="cyan-text text-lighten-3">n</span> = <span class="amber-text">0</span><span class="yellow-text">)</span>
    <span class="purple-text text-lighten-3">return</span> <span class="amber-text">1</span></pre>
<p>関数の処理の中で同じ関数を呼び出すというだけでは、永遠に処理が繰り返される<span class="bold">無限ループ</span>になってしまいます。 そこで、 factorial 関数では、 if 文を使って、もしも引数 n が 0 なら再帰呼び出しを行わずに <code><span class="purple-text text-lighten-3">return</span> <span class="amber-text">1</span></code> で戻り値として 1 を返しています（数学の約束で、 0 の階乗は 1 と決められているからです）。 これによって、再帰呼び出しによる繰り返しが終わるのです。</p>
<p>このように、再帰呼び出しを使うプログラムは、多くの場合に、 if 文を使って、ある条件なら同じ関数を呼び出して繰り返しを行い、ある条件なら同じ関数を呼び出さずに繰り返しを終える、という内容になります。</p>
<h2>再帰呼び出しの処理の流れ</h2>
<p>ここまでの説明で、再帰呼び出しの仕組みが何となくわかったと思いますが、 factorial 関数で引数 n の階乗が得られるまでの処理の流れがピンと来ないでしょう。</p>
<p>具体例として、引数 n = 3 のときの処理の流れをトレースしてみましょう。 3 の階乗は、<br />
3 × 2 × 1 =6<br />
です。 </p>
<p>以下に、 <code><span class="yellow-text text-lighten-4">factorial</span><span class="yellow-text">(</span><span class="amber-text">3</span><span class="yellow-text">)</span></code> を呼び出したときの処理の流れを示します。</p>
<div class="divider mag_h30"></div>
<dl class="inline mag_w20">
<dt class="chip indigo-text">手順 <i class="material-icons material-symbols-outlined">counter_1</i></dt>
<dd><code><span class="yellow-text text-lighten-4">factorial</span><span class="yellow-text">(</span><span class="amber-text">3</span><span class="yellow-text">)</span></code> が呼び出される。</dd>
<p></p>
<dt class="chip indigo-text">手順 <i class="material-icons material-symbols-outlined">counter_2</i></dt>
<dd><code><span class="purple-text text-lighten-3">return</span> <span class="amber-text">3</span> × <span class="yellow-text text-lighten-4">factorial</span><span class="yellow-text">(</span><span class="amber-text">2</span><span class="yellow-text">)</span></code> が行われ、 <code><span class="yellow-text text-lighten-4">factorial</span><span class="yellow-text">(</span><span class="amber-text">2</span><span class="yellow-text">)</span></code> が呼び出される。</dd>
<p></p>
<dt class="chip indigo-text">手順 <i class="material-icons material-symbols-outlined">counter_3</i></dt>
<dd><code><span class="purple-text text-lighten-3">return</span> <span class="amber-text">2</span> × <span class="yellow-text text-lighten-4">factorial</span><span class="yellow-text">(</span><span class="amber-text">1</span><span class="yellow-text">)</span></code> が行われ、 <code><span class="yellow-text text-lighten-4">factorial</span><span class="yellow-text">(</span><span class="amber-text">1</span><span class="yellow-text">)</span></code> が呼び出される。</dd>
<p></p>
<dt class="chip indigo-text">手順 <i class="material-icons material-symbols-outlined">counter_4</i></dt>
<dd><code><span class="purple-text text-lighten-3">return</span> <span class="amber-text">1</span> × <span class="yellow-text text-lighten-4">factorial</span><span class="yellow-text">(</span><span class="amber-text">0</span><span class="yellow-text">)</span></code> が行われ、 <code><span class="yellow-text text-lighten-4">factorial</span><span class="yellow-text">(</span><span class="amber-text">0</span><span class="yellow-text">)</span></code> が呼び出される。</dd>
<p></p>
<dt class="chip indigo-text">手順 <i class="material-icons material-symbols-outlined">counter_5</i></dt>
<dd>1 が返される。</dd>
<p></p>
<dt class="chip indigo-text">手順 <i class="material-icons material-symbols-outlined">counter_6</i></dt>
<dd><code><span class="purple-text text-lighten-3">return</span> <span class="amber-text">1</span> × <span class="yellow-text text-lighten-4">factorial</span><span class="yellow-text">(</span><span class="amber-text">0</span><span class="yellow-text">)</span></code> が <code><span class="purple-text text-lighten-3">return</span> <span class="amber-text">1</span> × 1</code> となって 1 が返される。</dd>
<p></p>
<dt class="chip indigo-text">手順 <i class="material-icons material-symbols-outlined">counter_7</i></dt>
<dd><code><span class="purple-text text-lighten-3">return</span> <span class="amber-text">2</span> × <span class="yellow-text text-lighten-4">factorial</span><span class="yellow-text">(</span><span class="amber-text">1</span><span class="yellow-text">)</span></code> が <code><span class="purple-text text-lighten-3">return</span> <span class="amber-text">2</span> × 1</code> となって 2 が返される。</dd>
<p></p>
<dt class="chip indigo-text">手順 <i class="material-icons material-symbols-outlined">counter_8</i></dt>
<dd><code><span class="purple-text text-lighten-3">return</span> <span class="amber-text">3</span> × <span class="yellow-text text-lighten-4">factorial</span><span class="yellow-text">(</span><span class="amber-text">2</span><span class="yellow-text">)</span></code> が <code><span class="purple-text text-lighten-3">return</span> <span class="amber-text">3</span> × 2</code> となって 6 が返される。</dd>
</dl>
<div class="divider mag_h30"></div>
<p>上記の処理の流れのポイントは、</p>
<pre>  <span class="purple-text text-lighten-3">return</span> <span class="cyan-text text-lighten-3">n</span> × <span class="yellow-text text-lighten-4">factorial</span><span class="yellow-text">(</span><span class="cyan-text text-lighten-3">n</span> - <span class="amber-text">1</span><span class="yellow-text">)</span></pre>
<p>において、すぐには戻り値を返す処理が行われずに（処理は保留になります）、 <code><span class="yellow-text text-lighten-4">factorial</span><span class="yellow-text">(</span><span class="cyan-text text-lighten-3">n</span> - <span class="amber-text">1</span><span class="yellow-text">)</span></code> という再帰呼び出しが行われることです。 この再帰呼び出しによる繰り返しは、引数が 0 になったときに <code><span class="purple-text text-lighten-3">return</span> <span class="amber-text">1</span></code> で 1 という戻り値を返すことで終わり、その後は、保留になっていた戻り値を返す処理が繰り返されます。</p>
<p>つまり、<br />
関数を呼んで → 呼んで → 呼んで、と繰り返し、<br />
戻り値を返して → 返して → 返して、と繰り返すのです。</p>
<p>3 の階乗は、 3 × 2 × 1 = 6 ですが、 1 の階乗を求めるときの 1 × (0 の階乗 ) において<br />
1 × 1<br />
という計算が行われるので、 3 × 2 × 1 × 1 = 6 で 6 が求められます。</p>
<h2>再帰呼び出しの穴埋め問題にチャレンジする</h2>
<p>試験対策として、プログラムの穴埋め問題にチャレンジしてみましょう。</p>
<p>これまでに例として示したプログラムと同じ内容ですが、再帰呼び出しの定番の例なので、確実に覚えてください。</p>
<div class="card-panel mag_h30">
リスト 2 は、引数 n の階乗を返す factorial 関数の定義です。 プログラム中の <span class="blank"></span> に入る正しい答えの組合せを解答群の中から選んでください。 引数 n は、 0 以上だとします。</p>
<figure><figcaption class="chip" style="height:auto;">リスト 2<i class="material-icons blue-text mag_w05">code</i> 引数 n の階乗を返す factorial 関数の定義</figcaption><pre>○<span class="blue-text">整数型</span>: <span class="yellow-text text-lighten-4">factorial</span><span class="yellow-text">(</span><span class="blue-text">整数型</span>: <span class="cyan-text text-lighten-3">n</span><span class="yellow-text">)</span>
  <span class="purple-text text-lighten-3">if</span> <span class="yellow-text">(</span><span class="cyan-text text-lighten-3">n</span> = <span class="amber-text">0</span><span class="yellow-text">)</span>
    <span class="purple-text text-lighten-3">return</span> <span class="blank">a</span>
  <span class="purple-text text-lighten-3">else</span>
    <span class="purple-text text-lighten-3">return</span> <span class="blank">b</span>
  <span class="purple-text text-lighten-3">endif</span></pre>
<p>解答群</p>
<table class="responsive-width striped centered">
<thead>
<tr>
<th></th>
<th>a</th>
<th>b</th>
</tr>
</thead>
<tbody>
<tr>
<td>ア</td>
<td>0</td>
<td>factorial(n &#8211; 1)</td>
</tr>
<tr>
<td>イ</td>
<td>0</td>
<td>n × factorial(n &#8211; 1)</td>
</tr>
<tr>
<td>ウ</td>
<td>1</td>
<td>factorial(n &#8211; 1)</td>
</tr>
<tr>
<td>エ</td>
<td>1</td>
<td>n × factorial(n &#8211; 1)</td>
</tr>
</tbody>
</table>
</div>
<p>空欄 a は、引数 n が 0 のときの処理です。 0 の階乗は 1 なので、 <code><span class="purple-text text-lighten-3">return</span> <span class="amber-text">1</span></code> という処理を行い、再帰呼び出しを行いません（再帰呼び出しによる繰り返しが終了します）。</p>
<p>空欄 b は、引数 n が 0 でないときの処理です。 ここでは、「 n の階乗は、 n × (n &#8211; 1) の階乗である」という考えで、 <code><span class="cyan-text text-lighten-3">n</span> × <span class="yellow-text text-lighten-4">factorial</span><span class="yellow-text">(</span><span class="cyan-text text-lighten-3">n</span> - <span class="amber-text">1</span><span class="yellow-text">)</span></code> という処理を行います。</p>
<p>したがって、正解は、選択肢エです。</p>
<div class="divider mag_tp50 mag_bt30"></div>
<p>今回は、再帰呼び出しを取り上げました。</p>
<p>次回以降も、シラバスに示されたアルゴリズムとデータ構造を学んでいきます。</p>
<p>それでは、またお会いしましょう！</p><p>The post <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/recursive/">再帰呼び出しのアルゴリズム｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</a> first appeared on <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi">基本情報技術者試験 受験ナビ｜科目A・科目B対策から過去問解説まで 250本以上の記事を掲載</a>.</p>]]></content:encoded>
			</item>
		<item>
		<title>サーチのアルゴリズム (2) 二分探索法｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</title>
		<link>https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/binary_search/</link>
		<pubDate>Mon, 08 May 2023 23:30:49 +0000</pubDate>
		<dc:creator><![CDATA[矢沢 久雄]]></dc:creator>
				<category><![CDATA[アルゴリズム]]></category>
		<category><![CDATA[科目 B]]></category>

		<guid isPermaLink="false">https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/?post_type=similar_programming&#038;p=7752</guid>
		<description><![CDATA[<p>基本情報技術者試験は、 2023 年 4 月から新制度で実施されています。 この連載では、新制度で採用された新しい擬似言語（旧制度の擬似言語とは、表記方法に違いがあります）を使って、試験のシラバス（情報処理技術者試験にお [&#8230;]</p>
<p>The post <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/binary_search/">サーチのアルゴリズム (2) 二分探索法｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</a> first appeared on <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi">基本情報技術者試験 受験ナビ｜科目A・科目B対策から過去問解説まで 250本以上の記事を掲載</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>基本情報技術者試験は、 2023 年 4 月から新制度で実施されています。</p>
<p>この連載では、新制度で採用された新しい擬似言語（旧制度の擬似言語とは、表記方法に違いがあります）を使って、試験のシラバス（情報処理技術者試験における知識・技能の細目）に示されている代表的なアルゴリズムとデータ構造を、プログラミング入門者向けにやさしく解説します。 受験対策としてだけでなく、アルゴリズムとプログラミングの基礎知識を習得するために、ぜひお読みください。</p>
<p>今回は、効率的なサーチアルゴリズムである <span class="bold">二分探索法</span> を取り上げます。</p>
<style>article,pre,code{font-family:'consolas','Courier New',"HCo Gotham SSm",Gotham,"ヒラギノ角ゴ Pro W3","Hiragino Kaku Gothic ProN","Hiragino Sans","BIZ UDPGothic",Meiryo,sans-serif!important;}pre,code{background:#263238;color:#eceff1;border-radius:unset;font-size:1em;line-height:1.8;position:relative;}pre{margin:auto -7.5%;padding:1em 7.5%;}.card-panel pre{margin:1em -24px}code{padding:.15em .25em;}.card-panel{box-shadow:0 4px 16px rgba(0,0,0,0.02),0 20px 46px rgba(0,0,0,0.08);}@media screen and (max-width:600px){dd{margin-left:.5em}}</style>
<h2>二分探索法のアルゴリズム</h2>
<p>図 1 に示したように、裏返された状態で 7 枚のトランプが並んでいるとします。 これらの中から、マークは何でもよいので 5 のカードを見つけるとしたら、どうしますか？ 「先頭（左端が先頭だとします）から順に 1 枚ずつめくって 5 かどうかをチェックする」と考えたなら、それで正解です。 そのアルゴリズムは、<a href="../sequential_search/">第 4 回の記事で紹介した「線形探索法」</a>です。</p>
<p>それでは、これら 7 枚のトランプが<span class="u">昇順（小さい順）にソートされている</span>としたら、どうしますか？ 線形探索法より効率的なアルゴリズムがありますので、ちょっと考えてみてください。 ポイントは、<span class="u bold">最初にどこをめくるか</span>です。</p>
<figure><figcaption>図 1　裏返されたトランプの中から 5 を見つける</figcaption><img class="materialboxed z-depth-5 responsive-width" src="../../wp-content/uploads/2023/05/playing_cards_image.jpg" loading="lazy"><br />
</figure>
<p>勘のいい人は「真ん中のカードをめくって、その値から探索対象を前側か後ろ側に絞り込む」というアルゴリズムを思い付いたでしょう。 それで正解です。 そのアルゴリズムを<span class="bold">「二分探索法」</span>と呼びます。</p>
<p>トランプ（プログラムでは配列）がランダムに並んでいたら、線形探索法を使うことになりますが、<span class="u">ソートされているなら二分探索法を使った方が効率的</span>です。 7 枚のトランプがある場合には、線形探索法では最大で 7 回カードをめくりますが、二分探索法では最大で 3 回カードをめくるだけで済みます。</p>
<p>図 2 に二分探索法で目的の値が見つかるまでの手順の例を示します。 </p>
<figure><figcaption>図 2　二分探索法で目的のカードが見つかるまでの手順の例</figcaption><img class="materialboxed mag_h00 z-depth-5 responsive-width" src="../../wp-content/uploads/2023/05/playing_cards_image_2.jpg" loading="lazy"><br />
  <img class="materialboxed mag_h00 z-depth-5 responsive-width" src="../../wp-content/uploads/2023/05/playing_cards_image_3.jpg" loading="lazy"><br />
  <img class="materialboxed mag_h00 z-depth-5 responsive-width" src="../../wp-content/uploads/2023/05/playing_cards_image_4.jpg" loading="lazy"><br />
</figure>
<p>7 枚のカードの探索対象は、 7 枚 → 3 枚 → 1 枚 と二分割されていきます。 だから二分探索と呼ぶのです。</p>
<p>ここでは、最後の 1 枚で見つかっていますが、その前の段階で見つかることも、最後までチェックして見つからないこともあります。</p>
<h2>二分探索法のプログラムの例</h2>
<p>リスト 1 は、二分探索法のプログラムの例です。 要素数 7 個の整数型の配列 a （昇順にソートされていて、要素番号は 0 から始まるとします）の中から変数 x と同じ値を見つけます。</p>
<p><span class="u">二分探索法のプログラムには、<span class="bold">決まりきった書き方</span>があります</span>。 これを、空手の型のように、プログラムの型として覚えてください。</p>
<p>なお、第 4 回の記事で説明したサーチアルゴリズムの基本である</p>
<div class="background c-round" style="position:relative;"><i class="material-icons blue-text" style="position:absolute;top:1em;left:1em;">format_quote</i></p>
<div class="mag_lt10">「見つかった場合は、見つかった位置（要素番号）を探索の結果とする」<br />
「見つかった場合は、その時点で探索を終了する」<br />
「見つからなかった場合は、配列の要素番号としてあり得ない -1 を探索の結果とする」</div>
<p><i class="material-icons blue-text" style="position:absolute;bottom:1em;right:1em;transform:rotateX(180deg);">format_quote</i>
</div>
<p>は、二分探索法でも同様です。 繰り返しを中断するのに、 break 文を使うことも使わないこともできるのも、線形探索法と同様です。 リスト 1 では、 break 文を使っていません。</p>
<p class="grey-text hide-on-med-and-up mag_h10 small-text"><i class="material-icons light-blue-text mag_rt05">swipe</i>プログラムは横スクロールできます</p>
<figure><figcaption class="chip" style="height:auto;">リスト 1<i class="material-icons blue-text mag_w05">code</i> 二分探索法のプログラムの例（その 1 ）</figcaption><pre><span class="blue-text">整数型の配列</span> <span class="cyan-text text-lighten-3">a</span> ← <span class="yellow-text text-lighten-4">{</span> <span class="amber-text">1</span>, <span class="amber-text">2</span>, <span class="amber-text">5</span>, <span class="amber-text">6</span>, <span class="amber-text">8</span>, <span class="amber-text">10</span>, <span class="amber-text">12</span> <span class="yellow-text text-lighten-4">}</span>
<span class="blue-text">整数型</span> <span class="cyan-text text-lighten-3">x</span>, <span class="cyan-text text-lighten-3">pos</span>, <span class="cyan-text text-lighten-3">left</span>, <span class="cyan-text text-lighten-3">mid</span>, <span class="cyan-text text-lighten-3">right</span>

<span class="grey-text">// 変数に初期値を設定する</span>
<span class="cyan-text text-lighten-3">x</span> ← <span class="amber-text">5</span>		<span class="grey-text">// 見つける値</span>
<span class="cyan-text text-lighten-3">pos</span> ← <span class="amber-text">-1</span>	<span class="grey-text">// 探索の結果</span>
<span class="cyan-text text-lighten-3">left</span> ← <span class="amber-text">0</span>	<span class="grey-text">// 探索対象の左端の要素番号</span>
<span class="cyan-text text-lighten-3">right</span> ← <span class="amber-text">6</span>	<span class="grey-text">// 探索対象の右端の要素番号</span>

<span class="grey-text">// まだ探索対象があり、かつ、まだ見つかってない限り、探索を繰り返す</span>
<span class="purple-text text-lighten-3">while</span> <span class="yellow-text">(</span><span class="cyan-text text-lighten-3">left</span> ≦ <span class="cyan-text text-lighten-3">right</span> and <span class="cyan-text text-lighten-3">pos</span> = <span class="amber-text">-1</span><span class="yellow-text">)</span>
<span class="cyan-text text-lighten-3">mid</span> ← <span class="yellow-text">(</span><span class="cyan-text text-lighten-3">left</span> + <span class="cyan-text text-lighten-3">right</span><span class="yellow-text">)</span> ÷ <span class="amber-text">2</span>	<span class="grey-text">// 真ん中の要素の要素番号を得る</span>
  <span class="purple-text text-lighten-3">if</span> <span class="yellow-text">(</span><span class="cyan-text text-lighten-3">a</span><span class="purple-text text-lighten-3">[</span><span class="cyan-text text-lighten-3">mid</span><span class="purple-text text-lighten-3">]</span> = <span class="cyan-text text-lighten-3">x</span><span class="yellow-text">)</span>		<span class="grey-text">// 真ん中の要素が見つける値と同じ場合</span>
    <span class="cyan-text text-lighten-3">pos</span> ← <span class="cyan-text text-lighten-3">mid</span>			<span class="grey-text">// 探索の結果に見つかった位置を設定する</span>
  <span class="purple-text text-lighten-3">elseif</span> <span class="yellow-text">(</span><span class="cyan-text text-lighten-3">a</span><span class="purple-text text-lighten-3">[</span><span class="cyan-text text-lighten-3">mid</span><span class="purple-text text-lighten-3">]</span> > <span class="cyan-text text-lighten-3">x</span><span class="yellow-text">)</span>		<span class="grey-text">// 真ん中の要素が見つける値より大きい場合</span>
    <span class="cyan-text text-lighten-3">right</span> ← <span class="cyan-text text-lighten-3">mid</span> - <span class="amber-text">1</span>		<span class="grey-text">// 真ん中より前側に探索対象を絞り込む</span>
  <span class="purple-text text-lighten-3">else</span>				<span class="grey-text">// 真ん中の要素が見つける値より小さい場合</span>
    <span class="cyan-text text-lighten-3">left</span> ← <span class="cyan-text text-lighten-3">mid</span> + <span class="amber-text">1</span>		<span class="grey-text">// 真ん中より後側に探索対象を絞り込む</span>
  <span class="purple-text text-lighten-3">endif</span>
<span class="purple-text text-lighten-3">endwhile</span>

<span class="grey-text">// 探索の結果を表示する</span>
<span class="yellow-text text-lighten-4">print</span><span class="yellow-text">(</span><span class="cyan-text text-lighten-3">pos</span><span class="yellow-text">)</span>
</pre>
</figure>
<p>リスト 1 の内容を詳しく説明しましょう。 </p>
<p>配列 a から変数 x と同じ値を見つけます。 探索の結果は、変数 pos に格納します。 ここでは、変数 x に 5 を設定しています。 変数 pos は、見つからなかったことを意味する -1 で初期化しています。</p>
<p>探索によって、 5 は <code><span class="cyan-text text-lighten-3">a</span><span class="purple-text text-lighten-3">[</span><span class="amber-text">2</span><span class="purple-text text-lighten-3">]</span></code> に見つかるので、変数 pos の値は 2 で上書きされます。 最後にある print は、引数の値を画面に表示する手続だとします。 <code><span class="yellow-text text-lighten-4">print</span><span class="yellow-text">(</span><span class="cyan-text text-lighten-3">pos</span><span class="yellow-text">)</span></code> によって、探索の結果が画面に表示されます。ここまでは、第 4 回で紹介した線形探索のプログラムと同様です。</p>
<h3>二分探索法の型</h3>
<p>変数 left 、 mid 、 right は、探索対象の左端、真ん中、左端の要素番号です。 これら <span class="u">3 つの変数を使うことが、二分探索法の型</span>です。 最初は、配列全体が探索対象なので、変数 left に先頭の要素番号の 0 を設定し、変数 right に末尾の要素番号の 6 を設定します。</p>
<p>&nbsp;</p>
<p>二分探索法では、 while 文を使った繰り返しを行います。 <span class="u">while 文のカッコの中に記述する</span></p>
<pre><span class="cyan-text text-lighten-3">left</span> ≦ <span class="cyan-text text-lighten-3">right</span> and <span class="cyan-text text-lighten-3">pos</span> = <span class="amber-text">-1</span></pre>
<p><span class="u">という条件も、二分探索法の型</span>です。 これは、「まだ探索対象があり、かつ、まだ見つかってない」という条件を意味しています。</p>
<p><code><span class="cyan-text text-lighten-3">pos</span> = <span class="amber-text">-1</span></code> が「まだ見つかっていない」という条件であることはわかると思いますが、どうして <code><span class="cyan-text text-lighten-3">left</span> ≦ <span class="cyan-text text-lighten-3">right</span></code> が「まだ探索対象がある」という条件になるか、わかりますか？</p>
<p>leftの初期値は配列の先頭であり、 right の初期値は配列の末尾なので</p>
<pre><span class="cyan-text text-lighten-3">left</span> &lt; <span class="cyan-text text-lighten-3">right</span></pre>
<p>です。 while文の繰り返しで、徐々に探索対象を狭めていくと、最後の 1 個の要素をチェックするときに</p>
<pre><span class="cyan-text text-lighten-3">left</span> = <span class="cyan-text text-lighten-3">right</span></pre>
<p>になります。 したがって、 <code><span class="cyan-text text-lighten-3">left</span> &lt; <span class="cyan-text text-lighten-3">right</span></code> から <code><span class="cyan-text text-lighten-3">left</span> = <span class="cyan-text text-lighten-3">right</span></code> までは探索対象があるので、これらをまとめて記述して</p>
<pre><span class="cyan-text text-lighten-3">left</span> ≦ <span class="cyan-text text-lighten-3">right</span></pre>
<p>になるのです。</p>
<p>&nbsp;</p>
<p><span class="u">while 文で繰り返される処理の内容も、二分探索法の型</span>です。</p>
<p>まず</p>
<pre><span class="cyan-text text-lighten-3">mid</span> ← <span class="yellow-text">(</span><span class="cyan-text text-lighten-3">left</span> + <span class="cyan-text text-lighten-3">right</span><span class="yellow-text">)</span> ÷ <span class="amber-text">2</span></pre>
<p>で、現在の探索対象の真ん中の要素番号を変数 mid に得ています。 真ん中は <code><span class="yellow-text">(</span><span class="cyan-text text-lighten-3">left</span> + <span class="cyan-text text-lighten-3">right</span><span class="yellow-text">)</span> ÷ <span class="amber-text">2</span></code> という計算で得られます。 変数 left とright は、整数型なので、割り算の小数点以下はカットされます。</p>
<p>次に、 if 文で真ん中の <code><span class="cyan-text text-lighten-3">a</span><span class="purple-text text-lighten-3">[</span><span class="cyan-text text-lighten-3">mid</span><span class="purple-text text-lighten-3">]</span></code> と変数 x の値を比べて、処理を 3 つに分岐させます。</p>
<dl>
<dt><i class="material-icons indigo-text">looks_one</i> もしも、真ん中の要素が見つける値と同じ場合 <code><span class="cyan-text text-lighten-3">a</span><span class="purple-text text-lighten-3">[</span><span class="cyan-text text-lighten-3">mid</span><span class="purple-text text-lighten-3">]</span> = <span class="cyan-text text-lighten-3">x</span></code></dt>
<dd class="mag_bt10"><i class="material-icons indigo-text">arrow_forward</i> 探索の結果に見つかった位置を設定します <code><span class="cyan-text text-lighten-3">pos</span> ← <span class="cyan-text text-lighten-3">mid</span></code></dd>
<dt><i class="material-icons indigo-text">looks_two</i> そうではなく、もしも、真ん中の要素が見つける値より大きい場合 <code><span class="cyan-text text-lighten-3">a</span><span class="purple-text text-lighten-3">[</span><span class="cyan-text text-lighten-3">mid</span><span class="purple-text text-lighten-3">]</span> > <span class="cyan-text text-lighten-3">x</span></code></dt>
<dd class="mag_bt10"><i class="material-icons indigo-text">arrow_forward</i> 真ん中より前側に探索対象を絞り込みます <code><span class="cyan-text text-lighten-3">right</span> ← <span class="cyan-text text-lighten-3">mid</span> - <span class="amber-text">1</span></code></dd>
<dt><i class="material-icons indigo-text">looks_3</i> そうではない場合 <code><span class="purple-text text-lighten-3">else</span></code></dt>
<dd><i class="material-icons indigo-text">arrow_forward</i> 真ん中の要素が見つける値より小さい場合なので、真ん中より後側に探索対象を絞り込みます <code><span class="cyan-text text-lighten-3">left</span> ← <span class="cyan-text text-lighten-3">mid</span> + <span class="amber-text">1</span></code></dd>
</dl>
<h2>二分探索法の穴埋め問題にチャレンジする</h2>
<p>試験対策として、二分探索法の穴埋め問題にチャレンジしてみましょう。</p>
<div class="card-panel mag_h30">
リスト 2 は、要素数 10 個（これまでの例より要素数が多くなっていることに注意してください）の配列 a から変数 x と同じ値を二分探索法で見つけるプログラムです。 プログラム中の <span class="blank"></span> に入る正しい答えの組合せを解答群の中から選んでください。 配列は、昇順にソートされていて、要素番号は 0 から始まるとします。</p>
<figure><figcaption class="chip" style="height:auto;">リスト 2<i class="material-icons blue-text mag_w05">code</i> 二分探索法のプログラムの例（その 2 ）</figcaption><pre><span class="blue-text">整数型の配列</span> <span class="cyan-text text-lighten-3">a</span> ← <span class="yellow-text text-lighten-4">{</span> <span class="amber-text">1</span>, <span class="amber-text">2</span>, <span class="amber-text">3</span>, <span class="amber-text">4</span>, <span class="amber-text">5</span>, <span class="amber-text">6</span>, <span class="amber-text">8</span>, <span class="amber-text">9</span>, <span class="amber-text">10</span>, <span class="amber-text">12</span>, <span class="amber-text">13</span> <span class="yellow-text text-lighten-4">}</span>
<span class="blue-text">整数型</span> <span class="cyan-text text-lighten-3">x</span>, <span class="cyan-text text-lighten-3">pos</span>, <span class="cyan-text text-lighten-3">left</span>, <span class="cyan-text text-lighten-3">mid</span>, <span class="cyan-text text-lighten-3">right</span>

<span class="cyan-text text-lighten-3">x</span> ← <span class="amber-text">8</span>
<span class="cyan-text text-lighten-3">pos</span> ← <span class="amber-text">-1</span>
<span class="cyan-text text-lighten-3">left</span> ← <span class="amber-text">0</span>
<span class="cyan-text text-lighten-3">right</span> ← <span class="blank">a</span>

<span class="purple-text text-lighten-3">while</span> <span class="yellow-text">(</span><span class="blank">b</span><span class="yellow-text">)</span>
<span class="cyan-text text-lighten-3">mid</span> ← <span class="yellow-text">(</span><span class="cyan-text text-lighten-3">left</span> + <span class="cyan-text text-lighten-3">right</span><span class="yellow-text">)</span> ÷ <span class="amber-text">2</span>
  <span class="purple-text text-lighten-3">if</span> <span class="yellow-text">(</span><span class="cyan-text text-lighten-3">a</span><span class="purple-text text-lighten-3">[</span><span class="cyan-text text-lighten-3">mid</span><span class="purple-text text-lighten-3">]</span> = <span class="cyan-text text-lighten-3">x</span><span class="yellow-text">)</span>
    <span class="cyan-text text-lighten-3">pos</span> ← <span class="cyan-text text-lighten-3">mid</span>
  <span class="purple-text text-lighten-3">elseif</span> <span class="yellow-text">(</span><span class="cyan-text text-lighten-3">a</span><span class="purple-text text-lighten-3">[</span><span class="cyan-text text-lighten-3">mid</span><span class="purple-text text-lighten-3">]</span> > <span class="cyan-text text-lighten-3">x</span><span class="yellow-text">)</span>
    <span class="cyan-text text-lighten-3">right</span> ← <span class="cyan-text text-lighten-3">mid</span> - <span class="amber-text">1</span>
  <span class="purple-text text-lighten-3">else</span>
    <span class="cyan-text text-lighten-3">left</span> ← <span class="cyan-text text-lighten-3">mid</span> + <span class="amber-text">1</span>
  <span class="purple-text text-lighten-3">endif</span>
<span class="purple-text text-lighten-3">endwhile</span>

<span class="yellow-text text-lighten-4">print</span><span class="yellow-text">(</span><span class="cyan-text text-lighten-3">pos</span><span class="yellow-text">)</span>
</pre>
<p>解答群</p>
<table class="responsive-width striped centered">
<thead>
<tr>
<th></th>
<th>a</th>
<th>b</th>
</tr>
</thead>
<tbody>
<tr>
<td>ア</td>
<td>9</td>
<td>left ≦ right and pos = -1</td>
</tr>
<tr>
<td>イ</td>
<td>9</td>
<td>right ≦ left and pos = -1</td>
</tr>
<tr>
<td>ウ</td>
<td>10</td>
<td>left ≦ right and pos = -1</td>
</tr>
<tr>
<td>エ</td>
<td>10</td>
<td>right ≦ left and pos = -1</td>
</tr>
</tbody>
</table>
</div>
<p>空欄 a は、探索対象の右端の要素番号に、配列の末尾の要素番号を設定する処理です。 ここでは、配列の要素数が 10 個で、要素番号は 0 から始まるので、末尾の要素番号は 9 です。</p>
<p>空欄 b は、探索を繰り返す条件です。 ここには、「まだ探索対象があり、かつ、まだ見つかってない」を意味する</p>
<pre><span class="cyan-text text-lighten-3">left</span> ≦ <span class="cyan-text text-lighten-3">right</span> and <span class="cyan-text text-lighten-3">pos</span> = <span class="amber-text">-1</span></pre>
<p>を指定します。 したがって、選択肢アが正解です。</p>
<div class="divider mag_tp50 mag_bt30"></div>
<p>今回は、効率的なサーチアルゴリズムである二分探索法を取り上げました。</p>
<p>次回は、再帰のアルゴリズムを取り上げる予定です。</p>
<p>それでは、またお会いしましょう！</p><p>The post <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/binary_search/">サーチのアルゴリズム (2) 二分探索法｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</a> first appeared on <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi">基本情報技術者試験 受験ナビ｜科目A・科目B対策から過去問解説まで 250本以上の記事を掲載</a>.</p>]]></content:encoded>
			</item>
		<item>
		<title>サーチのアルゴリズム (1) 線形探索法｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</title>
		<link>https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/sequential_search/</link>
		<pubDate>Tue, 04 Apr 2023 09:00:25 +0000</pubDate>
		<dc:creator><![CDATA[矢沢 久雄]]></dc:creator>
				<category><![CDATA[アルゴリズム]]></category>
		<category><![CDATA[科目 B]]></category>

		<guid isPermaLink="false">https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/?post_type=similar_programming&#038;p=7736</guid>
		<description><![CDATA[<p>基本情報技術者試験は、 2023 年 4 月から新制度で実施されます。 この連載では、新制度で採用される新しい擬似言語（旧制度の擬似言語とは、表記方法に違いがあります）を使って、試験のシラバス（情報処理技術者試験における [&#8230;]</p>
<p>The post <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/sequential_search/">サーチのアルゴリズム (1) 線形探索法｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</a> first appeared on <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi">基本情報技術者試験 受験ナビ｜科目A・科目B対策から過去問解説まで 250本以上の記事を掲載</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>基本情報技術者試験は、 2023 年 4 月から新制度で実施されます。</p>
<p>この連載では、新制度で採用される新しい擬似言語（旧制度の擬似言語とは、表記方法に違いがあります）を使って、試験のシラバス（情報処理技術者試験における知識・技能の細目）に示されている代表的なアルゴリズムとデータ構造を、プログラミング入門者向けにやさしく解説します。 受験対策としてだけでなく、アルゴリズムとプログラミングの基礎知識を習得するために、ぜひお読みください。</p>
<p>今回は、サーチアルゴリズムである <span class="bold">線形探索法</span> を取り上げます。</p>
<style>article,pre,code{font-family:'consolas','Courier New',"HCo Gotham SSm",Gotham,"ヒラギノ角ゴ Pro W3","Hiragino Kaku Gothic ProN","Hiragino Sans","BIZ UDPGothic",Meiryo,sans-serif!important;}pre,code{background:#263238;color:#eceff1;border-radius:unset;font-size:1em;line-height:1.8;position:relative;}pre{margin:auto -7.5%;padding:1em 7.5%;}.card-panel pre{margin:1em -24px}code{padding:.15em .25em;}.card-panel{box-shadow:0 4px 16px rgba(0,0,0,0.02),0 20px 46px rgba(0,0,0,0.08);}</style>
<h2>サーチアルゴリズムの基本</h2>
<p><span class="u">サーチ（ search = 探索）アルゴリズムは、配列の中から目的の値を見つけるアルゴリズム</span>です。</p>
<p>基本情報技術者試験のシラバスには、サーチアルゴリズムとして、</p>
<ul class="background c-round">
<li>線形探索法</li>
<li>二分探索法</li>
<li>ハッシュ表探索法</li>
</ul>
<p>が示されています。 今回は、線形探索法を取り上げます。 他のサーチアルゴリズムは、今後の記事の中で取り上げます。</p>
<p>&nbsp;</p>
<p>線形探索法からサーチアルゴリズムの基本を知ることができます。</p>
<p>例として、図 1 に示した配列 a （要素番号は 0 から始まるとします）から、変数 x と同じ値を見つけるとしましょう。</p>
<p>線形探索法のアルゴリズムは、とてもシンプルです。 <span class="u">配列の先頭から末尾に向かって要素を 1 つずつ順番に取り出して、変数 x と同じ値かどうかをチェックするだけ</span>です。 先頭から末尾まで一直線にチェックするので、線形探索法と呼ぶのです。</p>
<figure><figcaption>図 1　配列 a から変数 x と同じ値を線形探索する</figcaption><img class="materialboxed z-depth-5 responsive-width" src="../../wp-content/uploads/2023/04/sequential_search_image.jpg" loading="lazy"><br />
</figure>
<p>図 1 では、変数 x と同じ値が a[2] に見つかります。 この場合には、<span class="u">見つかった位置の 2 を探索の結果</span>とします。 これは、サーチアルゴリズムの基本です。 そして、見つかったら、その時点で探索を終了します。 これも、サーチアルゴリズムの基本です。</p>
<p>もしも、変数 x と同じ値が<span class="u">見つからなかった場合は、配列の要素番号としてあり得ない <span class="bold">-1</span> という値を探索の結果</span>とします（他の値でも構いませんが、多くの場合に -1 とします）。 これも、サーチアルゴリズムの基本です。</p>
<h2>線形探索法のプログラムの例</h2>
<p>リスト 1 は、先ほど図 1 に示した線形探索法の例を、擬似言語のプログラムにしたものです。 配列 a から変数 x と同じ値を探索します。</p>
<p>変数 pos には、探索の結果を格納します。 <span class="u">変数 pos の初期値を、見つからなかったことを意味する -1 にしていることに注目</span>してください。 この後にある for 文による繰り返しで、 a[0] ～ a[4] を順番にチェックし、もしも見つかったら</p>
<pre><span class="yellow-text">(</span><span class="cyan-text text-lighten-3">a</span><span class="purple-text text-lighten-3">[</span><span class="cyan-text text-lighten-3">i</span><span class="purple-text text-lighten-3">]</span> = <span class="cyan-text text-lighten-3">x</span><span class="yellow-text">)</span></pre>
<p>なら変数 pos の値を見つかった位置の i で上書きします。 こうすれば、変数 pos の値は、見つからなければ -1 のままであり、見つかれば見つかった位置になります。</p>
<p>このように、<span class="u">探索の結果を「見つからなかった」を意味する -1 で初期化</span>することも、サーチアルゴリズムの基本です。</p>
<p class="grey-text hide-on-med-and-up mag_h10 small-text"><i class="material-icons light-blue-text mag_rt05">swipe</i>プログラムは横スクロールできます</p>
<figure><figcaption class="chip" style="height:auto;">リスト 1<i class="material-icons blue-text mag_w05">code</i> 線形探索法のプログラムの例（その 1 ）</figcaption><pre><span class="blue-text">整数型の配列</span>: <span class="cyan-text text-lighten-3">a</span> ← <span class="yellow-text text-lighten-4">{</span> <span class="amber-text">56</span>, <span class="amber-text">34</span>, <span class="amber-text">90</span>, <span class="amber-text">78</span>, <span class="amber-text">12</span> <span class="yellow-text text-lighten-4">}</span>
<span class="blue-text">整数型</span>: <span class="cyan-text text-lighten-3">x</span>, <span class="cyan-text text-lighten-3">pos</span>, <span class="cyan-text text-lighten-3">i</span>
<span class="cyan-text text-lighten-3">x</span> ← <span class="amber-text">90</span>
<span class="cyan-text text-lighten-3">pos</span> ← <span class="amber-text">-1</span>

<span class="purple-text text-lighten-3">for</span> <span class="yellow-text">(</span> i を 0 から 4 まで 1 ずつ増やす<span class="yellow-text">)</span>
  <span class="purple-text text-lighten-3">if</span> <span class="yellow-text">(</span><span class="cyan-text text-lighten-3">a</span><span class="purple-text text-lighten-3">[</span><span class="cyan-text text-lighten-3">i</span><span class="purple-text text-lighten-3">]</span> = <span class="cyan-text text-lighten-3">x</span><span class="yellow-text">)</span>
    <span class="cyan-text text-lighten-3">pos</span> = <span class="cyan-text text-lighten-3">i</span>
    <span class="purple-text text-lighten-3">break</span>
  <span class="purple-text text-lighten-3">endif</span>
<span class="purple-text text-lighten-3">endfor</span>
<span class="yellow-text text-lighten-4">print</span><span class="yellow-text">(</span><span class="cyan-text text-lighten-3">pos</span><span class="yellow-text">)</span></pre>
</figure>
<p>if 文の処理の中にある <span class="u"><code><span class="purple-text text-lighten-3">break</span></code> は、<span class="bold">繰り返し処理を中断する命令</span></span>です。 擬似言語の記述形式を示した資料に break 命令はありませんが、 C 言語、 Java 、 Python など多くのプログラミング言語に break 命令があり、旧制度の試験問題でも break 命令が使われたことがあったので、新制度の試験問題でも break 命令が使われるでしょう。</p>
<p>プログラムの最後にある print は、引数の値を画面に表示する手続だとします。 <code><span class="yellow-text text-lighten-4">print</span><span class="yellow-text">(</span><span class="cyan-text text-lighten-3">pos</span><span class="yellow-text">)</span></code> によって、探索の結果が画面に表示されます。</p>
<h2>break 文を使わずに繰り返しを中断するテクニック</h2>
<p>先ほどのリスト 1 では、 break 命令を使いましたが、 break 命令を好まない出題者もいるでしょう。 リスト 2 は、リスト 1 と同じ機能のプログラムを、 break 命令を使わずに記述した例です。 リスト 1 では繰り返し処理に for 文を使っていましたが、リスト 2 では while 文を使っています。</p>
<figure><figcaption class="chip" style="height:auto;">リスト 2<i class="material-icons blue-text mag_w05">code</i> 線形探索法のプログラムの例（その 2 ）</figcaption><pre><span class="blue-text">整数型の配列</span>: <span class="cyan-text text-lighten-3">a</span> ← <span class="yellow-text text-lighten-4">{</span> <span class="amber-text">56</span>, <span class="amber-text">34</span>, <span class="amber-text">90</span>, <span class="amber-text">78</span>, <span class="amber-text">12</span> <span class="yellow-text text-lighten-4">}</span>
<span class="blue-text">整数型</span>: <span class="cyan-text text-lighten-3">x</span>, <span class="cyan-text text-lighten-3">pos</span>, <span class="cyan-text text-lighten-3">i</span>
<span class="cyan-text text-lighten-3">x</span> ← <span class="amber-text">90</span>
<span class="cyan-text text-lighten-3">pos</span> ← <span class="amber-text">-1</span>
<span class="cyan-text text-lighten-3">i</span> ← <span class="amber-text">0</span>

<span class="purple-text text-lighten-3">while</span> <span class="yellow-text">(</span><span class="cyan-text text-lighten-3">i</span> ≦ <span class="amber-text">4</span> and <span class="cyan-text text-lighten-3">pos</span> = <span class="amber-text">-1</span><span class="yellow-text">)</span>
  <span class="purple-text text-lighten-3">if</span> <span class="yellow-text">(</span><span class="cyan-text text-lighten-3">a</span><span class="purple-text text-lighten-3">[</span><span class="cyan-text text-lighten-3">i</span><span class="purple-text text-lighten-3">]</span> = <span class="cyan-text text-lighten-3">x</span><span class="yellow-text">)</span>
    <span class="cyan-text text-lighten-3">pos</span> = <span class="cyan-text text-lighten-3">i</span>
  <span class="purple-text text-lighten-3">endif</span>
  <span class="cyan-text text-lighten-3">i</span> ← <span class="cyan-text text-lighten-3">i</span> + <span class="amber-text">1</span>
<span class="purple-text text-lighten-3">endwhile</span>
<span class="yellow-text text-lighten-4">print</span><span class="yellow-text">(</span><span class="cyan-text text-lighten-3">pos</span><span class="yellow-text">)</span></pre>
<p>while 文のカッコの中にある</p>
<pre></span><span class="cyan-text text-lighten-3">i</span> ≦ <span class="amber-text">4</span> and <span class="cyan-text text-lighten-3">pos</span> = <span class="amber-text">-1</span></pre>
<p>という条件に注目してください。 </p>
<p><code><span class="cyan-text text-lighten-3">i</span> ≦ <span class="amber-text">4</span></code> は、 a[i] の i が 4 以下という条件なので「まだ末尾までチェックしていない」という意味です。<br />
<code><span class="cyan-text text-lighten-3">pos</span> = <span class="amber-text">-1</span></code> は、 pos が初期値の -1 のままであるという条件なので「まだ見つかっていない」という意味です。<br />
これら 2 つの条件を「かつ」を意味する <code>and</code> でつないでいるので、<span class="u">「まだ末尾までチェックしていない、かつ、まだ見つかっていない」</span>という条件が真である限り、探索が繰り返されます。</p>
<p>変数 x の値は a[2] に見つかるので、その時点で変数 pos に 2 が格納されます。 これによって「まだ見つかっていない」という条件が偽になり、「まだ末尾までチェックしていない、かつ、まだ見つかっていない」という条件も偽になるので探索が終了します。</p>
<p>このように、変数 pos の値を繰り返しの条件に使うことで、 break 文を使わずに繰り返し処理を中断できます。 プログラミングのテクニックとして覚えておいてください。</p>
<h2>線形探索の穴埋め問題にチャレンジする</h2>
<p>試験対策として、線形探索法の穴埋め問題にチャレンジしてみましょう。</p>
<div class="card-panel mag_h30">
リスト 3 は、要素数 10 個（<span class="u">これまでの例より要素数が多くなっていることに注意</span>してください）の配列 a から変数 x と同じ値を線形探索法で見つけるプログラム（ break 文を使わないプログラム）です。 プログラム中の<span class="blank"></span>に入る正しい答えの組合せを解答群の中から選んでください。 配列の要素番号は、 0 から始まるとします。</p>
<figure><figcaption class="chip" style="height:auto;">リスト 3<i class="material-icons blue-text mag_w05">code</i> 線形探索法のプログラムの例（その 3 ）</figcaption><pre><span class="blue-text">整数型の配列</span>: <span class="cyan-text text-lighten-3">a</span> ← <span class="yellow-text text-lighten-4">{</span> <span class="amber-text">89</span>, <span class="amber-text">99</span>, <span class="amber-text">56</span>, <span class="amber-text">34</span>, <span class="amber-text">90</span>, <span class="amber-text">67</span>, <span class="amber-text">23</span>, <span class="amber-text">78</span>, <span class="amber-text">12</span>, <span class="amber-text">45</span> <span class="yellow-text text-lighten-4">}</span>
<span class="blue-text">整数型</span>: <span class="cyan-text text-lighten-3">x</span>, <span class="cyan-text text-lighten-3">pos</span>, <span class="cyan-text text-lighten-3">i</span>
<span class="cyan-text text-lighten-3">x</span> ← <span class="amber-text">90</span>
<span class="cyan-text text-lighten-3">pos</span> ← <span class="blank">a</span>
<span class="cyan-text text-lighten-3">i</span> ← <span class="amber-text">0</span>

<span class="purple-text text-lighten-3">while</span> <span class="yellow-text">(</span><span class="blank">b</span><span class="yellow-text">)</span>
  <span class="purple-text text-lighten-3">if</span> <span class="yellow-text">(</span><span class="cyan-text text-lighten-3">a</span><span class="purple-text text-lighten-3">[</span><span class="cyan-text text-lighten-3">i</span><span class="purple-text text-lighten-3">]</span> = <span class="cyan-text text-lighten-3">x</span><span class="yellow-text">)</span>
    <span class="cyan-text text-lighten-3">pos</span> = <span class="cyan-text text-lighten-3">i</span>
  <span class="purple-text text-lighten-3">endif</span>
  <span class="cyan-text text-lighten-3">i</span> ← <span class="cyan-text text-lighten-3">i</span> + <span class="amber-text">1</span>
<span class="purple-text text-lighten-3">endwhile</span>
<span class="yellow-text text-lighten-4">print</span><span class="yellow-text">(</span><span class="cyan-text text-lighten-3">pos</span><span class="yellow-text">)</span></pre>
<p>解答群</p>
<table class="responsive-width striped centered">
<thead>
<tr>
<th></th>
<th>a</th>
<th>b</th>
</tr>
</thead>
<tbody>
<tr>
<td>ア</td>
<td>0</td>
<td>i ≦ 9 and pos = 0</td>
</tr>
<tr>
<td>イ</td>
<td>0</td>
<td>i ≦ 9 and pos = -1</td>
</tr>
<tr>
<td>ウ</td>
<td>-1</td>
<td>i ≦ 9 and pos = 0</td>
</tr>
<tr>
<td>エ</td>
<td>-1</td>
<td>i ≦ 9 and pos = -1</td>
</tr>
</tbody>
</table>
</div>
<p>配列の要素数が増えても、アルゴリズムは同じです。</p>
<p>空欄 a は、探索の結果を格納する変数 pos の初期値の設定です。 この初期値は、見つからなかったことを意味する -1 が適切です。</p>
<p>空欄 b は、繰り返しの条件です。「まだ末尾までチェックしていない、かつ、まだ見つかっていない」という条件にします。</p>
<p>ここでは、配列の要素が a[0] ～ a[9] なので、「まだ末尾までチェックしていない」は、 <code><span class="cyan-text text-lighten-3">i</span> ≦ <span class="amber-text">9</span></code> です。「まだ見つかっていない」は、これまでと同じ <code><span class="cyan-text text-lighten-3">pos</span> = <span class="amber-text">-1</span></code> です。</p>
<p>したがって、「まだ末尾までチェックしていない、かつ、まだ見つかっていない」は、</p>
<pre><span class="cyan-text text-lighten-3">i</span> ≦ <span class="amber-text">9</span> and <span class="cyan-text text-lighten-3">pos</span> = <span class="amber-text">-1</span></pre>
<p>です。</p>
<p>以上のことから、選択肢エが正解です。</p>
<div class="divider mag_tp50 mag_bt30"></div>
<p>今回は、基本的なサーチアルゴリズムである線形探索法を取り上げました。</p>
<p>次回は、効率的なサーチアルゴリズムである二分探索法を取り上げる予定です。</p>
<p>それでは、またお会いしましょう！</p><p>The post <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/sequential_search/">サーチのアルゴリズム (1) 線形探索法｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</a> first appeared on <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi">基本情報技術者試験 受験ナビ｜科目A・科目B対策から過去問解説まで 250本以上の記事を掲載</a>.</p>]]></content:encoded>
			</item>
		<item>
		<title>多重ループを使うバブルソート｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</title>
		<link>https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/bubble_sort_with_multiple_loop/</link>
		<pubDate>Sun, 05 Mar 2023 23:30:14 +0000</pubDate>
		<dc:creator><![CDATA[矢沢 久雄]]></dc:creator>
				<category><![CDATA[アルゴリズム]]></category>
		<category><![CDATA[科目 B]]></category>

		<guid isPermaLink="false">https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/?post_type=similar_programming&#038;p=7662</guid>
		<description><![CDATA[<p>基本情報技術者試験は、 2023 年 4 月から新制度で実施されます。 この連載では、新制度で採用される新しい擬似言語（旧制度の擬似言語とは、表記方法に違いがあります）を使って、試験のシラバス（情報処理技術者試験における [&#8230;]</p>
<p>The post <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/bubble_sort_with_multiple_loop/">多重ループを使うバブルソート｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</a> first appeared on <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi">基本情報技術者試験 受験ナビ｜科目A・科目B対策から過去問解説まで 250本以上の記事を掲載</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>基本情報技術者試験は、 2023 年 4 月から新制度で実施されます。</p>
<p>この連載では、新制度で採用される新しい擬似言語（旧制度の擬似言語とは、表記方法に違いがあります）を使って、試験のシラバス（情報処理技術者試験における知識・技能の細目）に示されている代表的なアルゴリズムとデータ構造を、プログラミング入門者向けにやさしく解説します。 受験対策としてだけでなく、アルゴリズムとプログラミングの基礎知識を習得するために、ぜひお読みください。</p>
<p>今回は、多重ループを使うソートアルゴリズムである <span class="bold">バブルソート</span> を取り上げます。</p>
<style>article,pre,code{font-family:'consolas','Courier New',"HCo Gotham SSm",Gotham,"ヒラギノ角ゴ Pro W3","Hiragino Kaku Gothic ProN","Hiragino Sans","BIZ UDPGothic",Meiryo,sans-serif!important;}pre,code{background:#263238;color:#eceff1;border-radius:unset;font-size:1em;line-height:1.8;position:relative;}pre{margin:auto -7.5%;padding:1em 7.5%;}.card-panel pre{margin:1em -24px}code{padding:.15em .25em;}.card-panel{box-shadow:0 4px 16px rgba(0,0,0,0.02),0 20px 46px rgba(0,0,0,0.08);}table{font-size:.85em;}ol.background{padding-left:3em!important;}</style>
<h2>前提知識として多重ループの流れを知る</h2>
<p><span class="u"><span class="bold">ソート（ sort = 整列）</span> とは、配列の要素を昇順（小さい順）または降順（大きい順）に並べ替えること</span>です。</p>
<p>試験のシラバスには、ソートアルゴリズムとして、</p>
<ul class="background c-round">
<li>バブルソート</li>
<li>選択ソート</li>
<li>挿入ソート</li>
<li>クイックソート</li>
<li>マージソート</li>
<li>ヒープソート</li>
</ul>
<p>が示されています。</p>
<p>これらの中で、バブルソート、選択ソート、挿入ソートは、繰り返しの中に繰り返しがある<span class="u"><span class="bold">多重ループ</span>（ loop = 繰り返し）を使うという点で共通</span>しています。 今回は、バブルソートだけを取り上げますが、多重ループでソートを行うポイントをつかめれば、選択ソートと挿入ソートも容易に理解できるでしょう。 クイックソート、マージソート、ヒープソートに関しては、別の機会に取り上げます。</p>
<p>&nbsp;</p>
<p>バブルソートのアルゴリズムを理解するための前提知識として、多重ループの流れを知っておきましょう。</p>
<p>多重ループという言葉だけを聞くと、とても難しく感じるかもしれませんが、日常生活にも普通に存在するものであり、決して難しくありません。 たとえば、 0 時 0 分から 23 時 59 分まで変化する 1 日の時計（デジタル時計）は、多重ループの好例です。 時の繰り返しの中に、分の繰り返しがあるからです。</p>
<h3>多重ループを使って 1 日の時計を表示するプログラム</h3>
<p>リスト 1 は、 1 日の時計を擬似言語のプログラムにしたものです（わかりやすいように色分けしています）。 </p>
<p>for 文は、繰り返しを表す構文であり、 for と endfor で囲まれた範囲にある処理が、 for の後のカッコの中にある制御記述（どのように繰り返すかを示した文や式など）に従って繰り返されます。</p>
<p>for 文のループ中に別の for 文のループがあることに注目してください。</p>
<p>外側のループでは、時を表す変数 hour が 0 から 23 まで 1 ずつ増えます。<br />
内側のループでは、分を表す変数 minute が 0 から 59 まで 1 ずつ増えます。</p>
<p>この多重ループの中で「 hour 時 minute 分を表示する」という処理が切り返されます。</p>
<p class="grey-text hide-on-med-and-up mag_h10 small-text"><i class="material-icons light-blue-text mag_rt05">swipe</i>プログラムは横スクロールできます</p>
<figure><figcaption class="chip" style="height:auto;"><i class="material-icons blue-text mag_w05">code</i> リスト 1  0 時 0 分から 23 時 59 分まで変化する 1 日の時計</figcaption><pre>整数型: <span class="blue-text">hour</span>, <span class="red-text">minute</span>
<span class="blue-text">for (hour を 0 から 23 まで 1 ずつ増やす)		// 外側のループ</span>
  <span class="red-text">for (minute を 0 から 59 まで 1 ずつ増やす)	// 内側のループ</span>
    <span class="blue-text">hour</span> 時 <span class="red-text">minute</span> 分を表示する
  <span class="red-text">endfor</span>
<span class="blue-text">endfor</span></pre>
</figure>
<p>多重ループの流れは「外側のループ変数（繰り返すたびに変化する変数）の値が固定された状態で、内側のループ変数が変化する」です。</p>
<p>リスト 1 の変化を順番に見てみましょう。</p>
<ol class="background c-round">
<li>外側のループ変数 hour が 0 に固定された状態で、内側のループ変数 minute が 0 から 59 まで 1 ずつ変化<br />
  <i class="material-icons">subdirectory_arrow_right</i> これによって 0 時 0 分から 0 時 59 分までが表示
</li>
<li>内側のループが終了すると、外側のループ変数 hour が変化<br />
  <i class="material-icons">subdirectory_arrow_right</i> ここでは、 1 ずつ増えるので、ループ変数 hour が 1 になる
</li>
<li>ループ変数 hour が 1 に固定された状態で、内側のループに入り直す</li>
<li>再びループ変数 minute が 0 から 59 まで 1 ずつ変化<br />
  <i class="material-icons">subdirectory_arrow_right</i> これによって 1 時 0 分から 1 時 59 分までが表示
</li>
</ol>
<p>以下同様に、 2 時 0 分から 2 時 59 分まで、 3 時 0 分から 3 時 59 分まで、 &#8230;&#8230;. 23 時 0 分から 23 時 59 分までが表示され、外側のループの終了によって、多重ループ全体が終了します。</p>
<p>&nbsp;</p>
<p>リスト 1 では、 for 文の中に別の for 文がある多重ループの例を示しましたが、 whil e文や do ～ while 文を使って多重ループを作ることもできます。 どの場合でも、多重ループは、外側のループ変数の値が固定された状態で、内側のループ変数が変化する、という流れになります。</p>
<h2>バブルソートのアルゴリズムを理解する</h2>
<p>バブルソートのアルゴリズムを大雑把に説明すると</p>
<p>「配列の後ろから前に向かって、</p>
<ol>
<li>隣り合った要素（ある要素と 1 つ前の要素）を比較</li>
<li>小さい方が前になるように交換</li>
</ol>
<p>という処理を繰り返す」です。</p>
<p>池の底から表面に泡が浮き上がるように、配列の後ろから前に小さな値が浮かび上がるので、バブル（ bubble = 泡）ソートと呼ぶのです。</p>
<p>プログラムを示す前に、手作業でバブルソートをやってみましょう。</p>
<p>図 1 に手順を示します。ここでは、要素数 4 個の配列 a を昇順にソートしています。 配列の要素番号（添字やインデックスとも呼びます）は、 1 から始まるとします。</p>
<figure><figcaption>図 1　バブルソートの手順</figcaption><img class="materialboxed z-depth-5 responsive-width" src="../../wp-content/uploads/2023/03/bubble_sort_image_1.jpg" loading="lazy"><br />
  <img class="materialboxed z-depth-5 responsive-width" src="../../wp-content/uploads/2023/03/bubble_sort_image_2.jpg" loading="lazy"><br />
  <img class="materialboxed z-depth-5 responsive-width" src="../../wp-content/uploads/2023/03/bubble_sort_image_3.jpg" loading="lazy"><br />
  <img class="materialboxed z-depth-5 responsive-width" src="../../wp-content/uploads/2023/03/bubble_sort_image_4.jpg" loading="lazy"><br />
  <img class="materialboxed z-depth-5 responsive-width" src="../../wp-content/uploads/2023/03/bubble_sort_image_5.jpg" loading="lazy"><br />
  <img class="materialboxed z-depth-5 responsive-width" src="../../wp-content/uploads/2023/03/bubble_sort_image_6.jpg" loading="lazy"><br />
</figure>
<p>図 1 の手順を理解できたら、どのようなループ変数の多重ループで、どのような処理が繰り返されるかを考えてみましょう。</p>
<p>バブルソートでは、決定する位置と比較位置が変化していきます。 後で示すプログラムに合わせて、決定する位置を変数 num 、比較位置を変数 pos で表すことにします。</p>
<ol class="background c-round">
<li>num を 1 に固定した状態で、 pos が 4 から 2 まで変化</li>
<li>num を 2 に固定した状態で、 pos が 4 から 3 まで変化</li>
<li>num を 3 に固定した状態で、 pos が 4 から 4 に変化<br />（ 4 と 4 は同じ値ですが他に合わせて変化と考えてください）</li>
</ol>
<p>このことから、 num が外側のループ変数であり、 pos が内側のループ変数であることがわかります。</p>
<p>外側のループ変数 num は、 1 （配列の先頭）から 3 （配列の末尾より 1 つ前の要素）まで 1 ずつ増えて変化します。 1 から 4 （配列の末尾の要素）でないのは、配列の末尾より 1 つ前の要素が決定すれば、残りの 1 つとなった末尾の要素は自動的に決定するからです。</p>
<p>内側のループ変数 pos は、 4 （配列の末尾）から、現在決定しようとしている位置 num の 1 つ右 (num + 1 ) まで 1 ずつ減って変化します。</p>
<p>&nbsp;</p>
<p>多重ループで繰り返される処理は「比較位置の要素と 1 つ前の要素を比較し、小さい方が前になるように交換する」です。</p>
<p>配列の名前を <code>a</code> とすれば、<br />
比較位置の要素は <code>a[pos]</code> であり、<br />
1 つ前の要素は <code>a[pos - 1]</code> です。</p>
<p><code>a[pos - 1] > a[pos]</code> という条件が真なら、 <code>a[pos]</code> と <code>a[pos - 1]</code> の値を交換します。</p>
<h2>バブルソートのプログラムを読み取る</h2>
<p>バブルソートが、どのようなループ変数の多重ループになり、どのような処理が繰り返されるかを理解できたらなら、プログラムも容易に理解できるでしょう。</p>
<p>リスト 2 は、先ほど図 1 で手順を示したバブルソートを擬似言語のプログラムにしたものです。</p>
<pre>整数型の配列: a ← { 78, 56, 34, 12 }</pre>
<p>は、「 78 」「 56 」「 34 」「 12 」という要素を持った配列 a を宣言しています。 整数型の変数 num と pos の役割は、これまでの説明と同じです。 整数型の変数 temp （ temporary = 一時的、という意味です）は、要素の値を交換するときに使います。</p>
<figure><figcaption class="chip" style="height:auto;"><i class="material-icons blue-text mag_w05">code</i> リスト 2  要素数 4 個の配列を昇順にバブルソートするプログラム</figcaption><pre>整数型の配列: a ← { 78, 56, 34, 12 }
整数型: <span class="blue-text">num</span>, <span class="red-text">pos</span>, temp
<span class="blue-text">for (num を 1 から 3 まで 1 ずつ増やす)		// 外側のループ</span>
  <span class="red-text">for (pos を 4 から num +1 まで 1 ずつ減らす)	// 内側のループ</span>
    if (a[<span class="red-text">pos</span> - 1] > a[<span class="red-text">pos</span>])
      temp ← a[<span class="red-text">pos</span>]
      a[<span class="red-text">pos</span>] ← a[<span class="red-text">pos</span> - 1]
      a[<span class="red-text">pos</span> - 1] ← temp
    endif
  <span class="red-text">endfor</span>
<span class="blue-text">endfor</span></pre>
</figure>
<p>変数 temp を使った値の交換も、覚えておくべきアルゴリズムです。 ここでは、 <code>a[pos]</code> と <code>a[pos - 1]</code> の値を交換します。</p>
<p>もしも、いきなり <code>a[pos] ← a[pos - 1]</code> を行ったら <code>a[pos]</code> の値が失われてしまうので、その前に</p>
<pre>temp ← a[pos]</pre>
<p>で <code>a[pos]</code> の値を変数 temp に一時的に逃がします。 <code>temp ← a[pos]</code> の後で、 <code>a[pos] ← a[pos - 1]</code> を行い、最後に </p>
<pre>a[pos - 1] ← temp</pre>
<p>を行えば、 <code>a[pos]</code> と <code>a[pos - 1]</code> の値を交換できます。</p>
<h2>バブルソートの穴埋め問題にチャレンジする</h2>
<p>試験対策として、バブルソートの穴埋め問題にチャレンジしてみましょう。</p>
<div class="card-panel mag_h30">
リスト 3 は、要素数 5 個（<span class="u">これまでの例より要素数が多くなっていることに注意</span>してください）の配列 a を昇順にバブルソートするプログラムです。 プログラム中の<span class="blank"></span>に入る正しい答えの組合せを解答群の中から選んでください。 配列の要素番号は、 1 から始まるとします。</p>
<figure><figcaption class="chip" style="height:auto;"><i class="material-icons blue-text mag_w05">code</i> リスト 3  要素数 5 個の配列を昇順にバブルソートするプログラム</figcaption><pre><span class="blue-text">整数型の配列</span>: <span class="cyan-text text-lighten-3">a</span> ← <span class="yellow-text text-lighten-4">{</span> <span class="amber-text">90</span>, <span class="amber-text">78</span>, <span class="amber-text">56</span>, <span class="amber-text">34</span>, <span class="amber-text">12</span> <span class="yellow-text text-lighten-4">}</span>
<span class="blue-text">整数型</span>: <span class="cyan-text text-lighten-3">num</span>, <span class="cyan-text text-lighten-3">pos</span>, <span class="cyan-text text-lighten-3">temp</span>
<span class="purple-text text-lighten-3">for</span> <span class="yellow-text">(</span><span class="blank">a</span><span class="yellow-text">)</span>  <span class="grey-text">// 外側のループ</span>
  <span class="purple-text text-lighten-3">for</span> <span class="yellow-text">(</span><span class="blank">b</span><span class="yellow-text">)</span>	<span class="grey-text">// 内側のループ</span>
    <span class="purple-text text-lighten-3">if</span> <span class="yellow-text">(</span><span class="purple-text text-lighten-3">[</span><span class="cyan-text text-lighten-3">pos</span> - <span class="amber-text">1</span><span class="purple-text text-lighten-3">]</span > a<span class="purple-text text-lighten-3">[</span><span class="cyan-text text-lighten-3">pos</span><span class="purple-text text-lighten-3">]</span<span class="yellow-text">)</span>
      <span class="cyan-text text-lighten-3">temp</span> ← <span class="cyan-text text-lighten-3">a</span><span class="yellow-text text-lighten-4">[</span><span class="cyan-text text-lighten-3">pos</span><span class="yellow-text text-lighten-4">]</span>
      <span class="cyan-text text-lighten-3">a</span><span class="yellow-text text-lighten-4">[</span><span class="cyan-text text-lighten-3">pos</span><span class="yellow-text text-lighten-4">]</span> ← <span class="cyan-text text-lighten-3">a</span><span class="yellow-text text-lighten-4">[</span><span class="cyan-text text-lighten-3">pos</span> - <span class="amber-text">1</span><span class="yellow-text text-lighten-4">]</span>
      <span class="cyan-text text-lighten-3">a</span><span class="yellow-text text-lighten-4">[</span><span class="cyan-text text-lighten-3">pos</span> - <span class="amber-text">1</span><span class="yellow-text text-lighten-4">]</span> ← <span class="cyan-text text-lighten-3">temp</span>
    <span class="purple-text text-lighten-3">endif</span>
  <span class="purple-text text-lighten-3">endfor</span>
<span class="purple-text text-lighten-3">endfor</span></pre>
</figure>
<p>解答群</p>
<table>
<thead>
<tr>
<th></th>
<th>a</th>
<th>b</th>
</tr>
</thead>
<tbody>
<tr>
<td>ア</td>
<td>pos を num + 1 から 5 まで 1 ずつ増やす</td>
<td>num を 4 から 1 まで 1 ずつ減らす</td>
</tr>
<tr>
<td>イ</td>
<td>num を 4 から 1 まで 1 ずつ減らす</td>
<td>pos を num + 1 から 5 まで 1 ずつ増やす</td>
</tr>
<tr>
<td>ウ</td>
<td>pos を 5 から num + 1 まで 1 ずつ減らす</td>
<td>num を 1 から 4 まで 1 ずつ増やす</td>
</tr>
<tr>
<td>エ</td>
<td>num を 1 から 4 まで 1 ずつ増やす</td>
<td>pos を 5 から num + 1 まで 1 ずつ減らす</td>
</tr>
</tbody>
</table>
</div>
<p>要素数が増えても、アルゴリズムは同じです。</p>
<p>外側のループ変数 num は、配列の先頭から末尾より 1 つ前まで 1 ずつ増えて変化します。<br />
内側のループ変数 pos は、配列の末尾から現在決定しようとしている位置 num の 1 つ右 <code>(num + 1)</code> まで 1 ずつ減って変化します。</p>
<p>ここでは、配列の要素が a[1] から a[5] なので、外側の for 文の制御記述は</p>
<pre>num を 1 から 4 まで 1 ずつ増やす</pre>
<p>であり、内側の for 文の制御記述は</p>
<pre>pos を 5 から num + 1 まで 1 ずつ減らす</pre>
<p>です。</p>
<p>したがって、選択肢エが正解です。</p>
<div class="divider mag_tp50 mag_bt30"></div>
<p>今回は、多重ループを使うソートアルゴリズムであるバブルソートを取り上げました。</p>
<p>次回以降も、シラバスに示されたアルゴリズムとデータ構造を学んでいきます。</p>
<p>それでは、またお会いしましょう！</p><p>The post <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/similar_programming/bubble_sort_with_multiple_loop/">多重ループを使うバブルソート｜新しい擬似言語で学ぶ 科目 B アルゴリズムとプログラミング入門</a> first appeared on <a href="https://www.seplus.jp/dokushuzemi/ec/fe/fenavi">基本情報技術者試験 受験ナビ｜科目A・科目B対策から過去問解説まで 250本以上の記事を掲載</a>.</p>]]></content:encoded>
			</item>
	</channel>
</rss>
