質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
連結リスト

連結リストとは、データ構造のひとつであるリストの中で、要素が前後の要素の情報を持つことで、要素が連結(リンク)しているリストの事を呼びます。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

Q&A

解決済

2回答

1534閲覧

Kotlinで双方向連結リストを実装したい。特にGetEnumeratorと型引数Tらへんに困ってます。

picohead

総合スコア8

連結リスト

連結リストとは、データ構造のひとつであるリストの中で、要素が前後の要素の情報を持つことで、要素が連結(リンク)しているリストの事を呼びます。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

0グッド

0クリップ

投稿2020/10/27 14:20

編集2020/12/02 13:16

前提・実現したいこと

Kotlinで双方向連結リストを実装したい。
前提として下記サイトを参考にした。
双方向連結リスト - アルゴリズムとデータ構造 | ++C++; // 未確認飛行 C

発生している問題・エラーメッセージ

kotlinc-jvm.bat ".\BidirectionalLinkedList.kt" -include-runtime -d ".\BidirectionalLinkedList.jar"

一旦、上記でコンパイルが通るよう修正しました。
新たな問題点は3点。(編集前の4点は保留)
(5)(4)とほぼ同義だが、型引数Tの指定方法がよくわからない。とりあえずAny?に変更した。
(6)NodeクラスもBidirectionalLinkedListIteratorクラスもBidirectionalLinkedListにだけ見えるようにしたいが、単純に内部クラスにしてしまうと、~IteratorクラスからNodeクラスが見えない。
(7)IteratorとかIterableの継承方法がよくわからない。

該当のソースコード

Kotlin

1//https://ufcpp.net/study/algorithm/col_blist.html 2 3package Collections; 4 5 6///<summary> 7/// 双方向連結リスト。 8///</summary> 9///<typeparam name = "T">要素の型</typeparam> 10public class BidirectionalLinkedList { 11 12 //#region フィールド 13 14 public val dummy: Node; 15 public var count: Int; 16 17 //#endregion 18 19 //#region 初期化 20 21 public constructor() { 22 this.dummy = Node(null, null, null); 23 this.dummy.Next = this.dummy; 24 this.dummy.Previous = this.dummy; 25 this.count = 0; 26 } 27 28 //#endregion 29 30 //#region プロパティ 31 32 public val First: Node? 33 get() = this.dummy.Next; 34 35 public val Last: Node? 36 get() = this.dummy.Previous; 37 38 ///<summary> 39 /// リストの終端(末尾よりも後ろの番兵に当たるノード)。 40 ///</summary> 41 public val End: Node? 42 get() = this.dummy; 43 44 //#endregion 45 46 //#region 挿入・削除 47 48 ///<summary> 49 /// ノード n の後ろに新しい要素を追加。 50 ///</summary> 51 ///<param name = "e">新しい要素</param> 52 ///<param name = "n">要素の挿入位置</param> 53 ///<returns>新しく挿入されたノード</returns> 54 public fun InsertEAfterN(e: Any?, n: Node?): Node? { 55 val m: Node? = Node(e, n, n?.Next); 56 n?.Next?.Previous = m; 57 n?.Next = m; 58 this.count++; 59 return m; 60 } 61 62 ///<summary> 63 /// ノード n の前に新しい要素を追加。 64 ///</summary> 65 ///<param name = "e">新しい要素</param> 66 ///<param name = "n">要素の挿入位置</param> 67 ///<returns>新しく挿入されたノード</returns> 68 public fun InsertEBeforeN(e: Any?, n: Node?): Node? { 69 val m: Node? = Node(e, n?.Previous, n); 70 n?.Previous?.Next = m; 71 n?.Previous = m; 72 this.count++; 73 return m; 74 } 75 76 ///<summary> 77 /// 先頭に新しい要素を追加。 78 ///</summary> 79 ///<param name = "elem">新しい要素</param> 80 ///<returns>新しく挿入されたノード</returns> 81 public fun InsertFirst(elem: Any?): Node? { 82 return this.InsertEAfterN(elem, this.dummy); 83 } 84 85 ///<summary> 86 /// 末尾に新しい要素を追加。 87 ///</summary> 88 ///<param name = "elem">新しい要素</param> 89 ///<returns>新しく挿入されたノード</returns> 90 public fun InsertLast(elem: Any?): Node? { 91 return this.InsertEBeforeN(elem, this.dummy); 92 } 93 94 ///<summary> 95 /// ノード n 自身を削除。 96 ///</summary> 97 ///<param name = "n">要素の削除位置</param> 98 ///<returns>削除した要素の次のノード</returns> 99 public fun Erase(n: Node?): Node? { 100 if (n == this.dummy) { 101 return this.dummy; 102 } 103 n?.Previous?.Next = n?.Next; 104 n?.Next?.Previous = n?.Previous; 105 this.count--; 106 return n?.Next; 107 } 108 109 ///<summary> 110 /// 先頭の要素を削除。 111 ///</summary> 112 public fun EraseFirst(): Unit { 113 this.Erase(this.First); 114 } 115 116 ///<summary> 117 /// 末尾の要素を削除。 118 ///</summary> 119 public fun EraseLast(): Unit { 120 this.Erase(this.Last); 121 } 122 123 //#endregion 124 125 //#region IEnumerable<T>メンバ 126 127 operator fun iterator() = BidirectionalLinkedListIterator(this); 128 129 //#endregion 130 131} 132 133public class BidirectionalLinkedListIterator(val list: BidirectionalLinkedList) { 134 private var n: Node? = list.First; 135 fun next(): Node? { 136 return n?.Next; 137 } 138 fun hasNext(): Boolean { 139 return n != list.End; 140 } 141} 142 143///<summary> 144/// 連結リストのノード。 145///</summary> 146public class Node { 147 148 //#region フィールド 149 150 private var value: Any?; 151 private var prev: Node?; 152 private var next: Node?; 153 154 //#endregion 155 156 //#region 初期化 157 158 internal constructor(_value: Any?, _prev: Node?, _next: Node?) { 159 this.value = _value; 160 this.prev = _prev; 161 this.next = _next; 162 } 163 164 //#endregion 165 166 //#region プロパティ 167 168 public var Value: Any? 169 get() = this.value; 170 set(value) { 171 this.value = value; 172 } 173 174 /// <summary> 175 /// 前のノード。 176 /// </summary> 177 var Previous: Node? 178 get() = this.prev; 179 internal set(value) { 180 this.prev = value; 181 } 182 183 /// <summary> 184 /// 次のノード。 185 /// </summary> 186 var Next: Node? 187 get() = this.next; 188 internal set(value) { 189 this.next = value; 190 } 191 192 //#endregion 193 194}

試したこと

(1)Kotlinで調べても全然情報が見つからないため、主にjavaで調べたのですが、GetEnumeratorなどの実装例が見つからず断念。
Iteratorを試そうとしたが、現在のNode?の指定方法や初期化が不明なために断念。とりあえずコメントアウト。
(2)他作クラスがどこにあるのかわからず、クラスパス?へ設定できずimportも保留。
(4)Kotlinの和訳リファレンスやネットで使用例などを見る限り、型引数の使い方も間違ってなさそうに見えるがダメらしい。

補足情報(FW/ツールのバージョンなど)

・kotlincは1.3.60

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自己解決

可視性修飾子をちゃんと最低限にしたり、いきなりNodeクラスにするのではなくNodeクラスを継承したBidirectionalNodeクラスとしたかったり、色々思うところはありますが、とりあえず動作確認までできました。

コマンドプロンプト

kotlinc-jvm.bat Node.kt -d Node.jar kotlinc-jvm.bat BidirectionalLinkedList.kt -cp ".\Node.jar" -d BidirectionalLinkedList.jar kotlinc-jvm.bat test.kt -cp ".\Node.jar;.\BidirectionalLinkedList.jar" -include-runtime -d test.jar java -cp ".\Node.jar;.\BidirectionalLinkedList.jar;.\test.jar" TestKt

Node.kt

Kotlin

1//https://ufcpp.net/study/algorithm/col_blist.html 2 3//package Collections; 4 5///<summary> 6/// 連結リストのノード。 7///</summary> 8///<typeparam name = "T">要素の型</typeparam> 9public class Node<T> { 10 11 //#region フィールド 12 private var value: T; 13 private var prev: Node<T>; 14 private var next: Node<T>; 15 //#endregion 16 17 //#region 初期化 18 constructor(_value: T, _prev: Node<T>?, _next: Node<T>?) { 19 this.value = _value; 20 this.prev = _prev?:this; 21 this.next = _next?:this; 22 } 23 //#endregion 24 25 //#region プロパティ 26 27 public var Value: T 28 get() = this.value; 29 set(value) { 30 this.value = value; 31 } 32 33 /// <summary> 34 /// 前のノード。 35 /// </summary> 36 var Previous: Node<T> 37 get() = this.prev; 38// internal set(value) { 39 set(value) { 40 this.prev = value; 41 } 42 43 /// <summary> 44 /// 次のノード。 45 /// </summary> 46 var Next: Node<T> 47 get() = this.next; 48// internal set(value) { 49 set(value) { 50 this.next = value; 51 } 52 53 //#endregion 54 55}

BidirectionalLinkedList.kt

Kotlin

1//https://ufcpp.net/study/algorithm/col_blist.html 2 3//package Collections; 4 5interface Iterator<T> { 6 operator fun hasNext() : Boolean 7 operator fun next() : Node<T> 8} 9interface Aggregate<T> { 10 operator fun iterator() : Iterator<T> 11} 12 13///<summary> 14/// 双方向連結リスト。 15///</summary> 16///<typeparam name = "T">要素の型</typeparam> 17public class BidirectionalLinkedList<T> : Aggregate<T> { 18 19 //#region フィールド 20 public val dummy: Node<T>; 21 public var count: Int; 22 //#endregion 23 24 //#region 初期化 25 public constructor(init: T) { 26 this.dummy = Node<T>(init, null, null); 27 this.dummy.Next = this.dummy; 28 this.dummy.Previous = this.dummy; 29 this.count = 0; 30 } 31 //#endregion 32 33 //#region プロパティ 34 35 public val First: Node<T> 36 get() = this.dummy.Next; 37 38 public val Last: Node<T> 39 get() = this.dummy.Previous; 40 41 ///<summary> 42 /// リストの終端(末尾よりも後ろの番兵に当たるノード)。 43 ///</summary> 44 public val End: Node<T> 45 get() = this.dummy; 46 47 //#endregion 48 49 //#region メソッド 50 51 ///<summary> 52 /// ノード n の後ろに新しい要素を追加。 53 ///</summary> 54 ///<param name = "e">新しい要素</param> 55 ///<param name = "n">要素の挿入位置</param> 56 ///<returns>新しく挿入されたノード</returns> 57 public fun InsertEAfterN(e: T, n: Node<T>): Node<T> { 58 val m: Node<T> = Node<T>(e, n, n.Next); 59 n.Next.Previous = m; 60 n.Next = m; 61 this.count++; 62 return m; 63 } 64 65 ///<summary> 66 /// ノード n の前に新しい要素を追加。 67 ///</summary> 68 ///<param name = "e">新しい要素</param> 69 ///<param name = "n">要素の挿入位置</param> 70 ///<returns>新しく挿入されたノード</returns> 71 public fun InsertEBeforeN(e: T, n: Node<T>): Node<T> { 72 val m: Node<T> = Node<T>(e, n.Previous, n); 73 n.Previous.Next = m; 74 n.Previous = m; 75 this.count++; 76 return m; 77 } 78 79 ///<summary> 80 /// 先頭に新しい要素を追加。 81 ///</summary> 82 ///<param name = "e">新しい要素</param> 83 ///<returns>新しく挿入されたノード</returns> 84 public fun InsertFirst(e: T): Node<T> { 85 return this.InsertEAfterN(e, this.dummy); 86 } 87 88 ///<summary> 89 /// 末尾に新しい要素を追加。 90 ///</summary> 91 ///<param name = "e">新しい要素</param> 92 ///<returns>新しく挿入されたノード</returns> 93 public fun InsertLast(e: T): Node<T> { 94 return this.InsertEBeforeN(e, this.dummy); 95 } 96 97 ///<summary> 98 /// ノード n 自身を削除。 99 ///</summary> 100 ///<param name = "n">要素の削除位置</param> 101 ///<returns>削除した要素の次のノード</returns> 102 public fun Erase(n: Node<T>): Node<T> { 103 if (n == this.dummy) { 104 return this.dummy; 105 } 106 n.Previous.Next = n.Next; 107 n.Next.Previous = n.Previous; 108 this.count--; 109 return n.Next; 110 } 111 112 //#endregion 113 114 //#region interfaceの実装 115 public override fun iterator(): Iterator<T> { 116 return BidirectionalLinkedListIterator<T>(this); 117 } 118 119 public class BidirectionalLinkedListIterator<T>(val list: BidirectionalLinkedList<T>) : Iterator<T>{ 120 private var n: Node<T> = list.End; 121 override fun next(): Node<T> { 122 n = n.Next; 123 return n; 124 } 125 override fun hasNext(): Boolean { 126 return n.Next !== list.End; 127 } 128 } 129 //#endregion 130 131}

test.kt

Kotlin

1fun main(args: Array<String>) { 2 println("----Float----\n"); 3 4 var blly: BidirectionalLinkedList<Float> = BidirectionalLinkedList<Float>(1.5F); 5 println("count: "+blly.count);//0 6 println("----for start----"); 7 for (ny: Node<Float> in blly) { 8 println(ny.Value); 9 } 10 println("----for end----\n"); 11 blly.InsertFirst(1F); 12 println("count: "+blly.count);//1 13 println("----for start----"); 14 for (ny: Node<Float> in blly) { 15 println(ny.Value); 16 } 17 println("----for end----\n"); 18 var n2y: Node<Float> = blly.InsertLast(2F); 19 println(n2y.Value);//2 20 println("count: "+blly.count);//2 21 println("----for start----"); 22 for (ny: Node<Float> in blly) { 23 println(ny.Value);//1,2 24 } 25 println("----for end----\n"); 26 blly.InsertEBeforeN(1.5F,n2y); 27 println("count: "+blly.count);//3 28 println("----for start----"); 29 for (ny: Node<Float> in blly) { 30 println(ny.Value);//1,1.5,2 31 } 32 println("----for end----\n"); 33 34 println("\n\n\n"); 35 36 println("----Int?----\n"); 37 38 var blln: BidirectionalLinkedList<Int?> = BidirectionalLinkedList<Int?>(null); 39 println("count: "+blln.count);//0 40 println("----for start----"); 41 for (nn: Node<Int?> in blln) { 42 println(nn.Value?: "nullです"); 43 } 44 println("----for end----\n"); 45 blln.InsertFirst(1); 46 println("count: "+blln.count);//1 47 println("----for start----"); 48 for (nn: Node<Int?> in blln) { 49 println(nn.Value?: "nullです"); 50 } 51 println("----for end----\n"); 52 var n2n: Node<Int?> = blln.InsertLast(2); 53 println(n2n.Value?: "nullです");//2 54 println("count: "+blln.count);//2 55 println("----for start----"); 56 for (nn: Node<Int?> in blln) { 57 println(nn.Value?: "nullです");//1,2 58 } 59 println("----for end----\n"); 60 blln.InsertEBeforeN(null,n2n); 61 println("count: "+blln.count);//3 62 println("----for start----"); 63 for (nn: Node<Int?> in blln) { 64 println(nn.Value?: "nullです");//1,nullです,2 65 } 66 println("----for end----\n"); 67 blln.Erase(n2n); 68 println("count: "+blln.count);//2 69 println("----for start----"); 70 for (nn: Node<Int?> in blln) { 71 println(nn.Value?: "nullです");//1,nullです 72 } 73 println("----for end----\n"); 74 blln.Erase(blln.First); 75 println("count: "+blln.count);//1 76 println("----for start----"); 77 for (nn: Node<Int?> in blln) { 78 println(nn.Value?: "nullです");//nullです 79 } 80 println("----for end----\n"); 81 blln.Erase(blln.Last); 82 println("count: "+blln.count);//0 83 println("----for start----"); 84 for (nn: Node<Int?> in blln) { 85 println(nn.Value?: "nullです");// 86 } 87 println("----for end----\n"); 88}

投稿2021/02/17 14:29

picohead

総合スコア8

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

→(1)GetEnumerator周辺の実装方法がわからない

実装できません

→(2)System.Collections.Genericのインポート方法がわからない

インポートできません

→(3)上のインポートができれば解決するはず。。。

インポートできないので解決しません

→(4)全般的に型引数Tが参照できない

inner class にしてください

C#のコードをもとにkotlinを書きたいのであれば、C#上での動作を理解したうえでkotlinでそれを再現するしかありません。kotlinでの書き方がわからないからといってC#のコードをそのまま持ってきて穴埋めするのでは動くわけありません。

投稿2020/11/11 02:20

yudedako67

総合スコア2047

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

picohead

2020/11/11 13:16

ご回答ありがとうございます。 C#のコードを元にはできないのですね。。。 私はKotlinで双方向連結リストを実装したいのであって、C#を元にしたいわけではないのでそこは諦めます。 KotlinでもMutableListなどのリストが使用できます。あれはどのように実装されているのでしょうか。 あれもfor(A in B)でループできて、型引数を渡しているため、あれがわかれば私が詰まってるとこがちょうど解決できる見込みです。
yudedako67

2020/11/11 16:59

Iterableを実装して、Iteratorを実装したオブジェクトを返すようにすればできます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問