Java プログラミング スキル - データ構造とアルゴリズム「単方向リンク リスト」

Java プログラミング スキル - データ構造とアルゴリズム「単方向リンク リスト」

[[386512]]

基本的な紹介

リンクリストは順序付きリストですが、メモリ内に次のように保存されます。


  1. リンクリストはノードの形式で保存されます。
  2. 各ノードにはデータ フィールドと次のフィールド (次のノードを指す) が含まれます。
  3. 図に示すように、各リンクリストのノードは必ずしも連続して格納されるわけではないことがわかります。
  4. リンク リストは、ヘッド ノードを持つリンク リストとヘッド ノードを持たないリンク リストに分けられ、実際のニーズに応じて決定されます。

単連結リストの紹介

単一リンクリスト(ヘッドノード付き)の論理構造図は次のようになります。


単連結リストの応用例

ヘッド付きの一方向リンクリストを使用してウォーター・マージンヒーローランキング管理を実装する

  1. パッケージ com.structures.linkedlist;
  2.  
  3. パブリッククラスSingleLinkedListDemo {
  4. 公共 静的void main(String[] args) {
  5. HeroNode heroNode1 = new HeroNode(1, "Song Jiang" , "Timely Rain" );
  6. HeroNode heroNode2 = new HeroNode(2, "Lu Junyi" , "Yu Qilin" );
  7. HeroNode heroNode3 = new HeroNode(3, "Wu Yong" , "Zhi Duo Xing" );
  8. HeroNode heroNode4 = new HeroNode(4, "Lin Chong" , "Leopard Head" );
  9. シングルリンクリスト singleLinkedList = 新しいシングルリンクリスト();
  10. シングルリンクリストを追加します(heroNode3);
  11. シングルリンクリストを追加します(heroNode2);
  12. シングルリンクリストを追加します(heroNode4);
  13. 単一のLinkedListを追加します(heroNode1);
  14. シングルリンクリスト.list();
  15. }
  16. }
  17.  
  18. //ヒーローを管理するためにSingleLinkedListを定義する
  19. クラスSingleLinkedList {
  20. //まずヘッドノードを初期化します。ヘッドノードは移動できず、将来のトラバーサルに使用されます。
  21. プライベートHeroNodeヘッド = 新しいHeroNode(0, "" , "" );
  22.  
  23. // 単一リンクリストにノードを追加する
  24. // アイデア: 数字の順序を考慮しない場合
  25. //1. 現在のリンクリストの最後のノードを見つける
  26. //2. 最後のノードの次のフィールドを新しいノードにポイントする
  27. パブリックvoid追加(HeroNode ノード) {
  28. //ヘッドノードは移動できないため、補助的なトラバーサルテンポが必要です 
  29. HeroNode temp = ヘッド;
  30. //リンクリストを走査して最後の
  31. while ( temp . next != null ) {
  32. // リンクリストの末尾を見つける
  33. // tempが見つからない場合は戻る
  34. temp = temp . next ;
  35. }
  36. temp . next = ノード;
  37. }
  38.  
  39. //リンクリストを表示する [トラバーサル]
  40. パブリックボイドリスト(){
  41. // リンクリストが空かどうか確認する
  42. head.next == nullの場合){
  43. System.out.println ( "リンクリストは空です" );
  44. }
  45. //ヘッドノードは移動できないため、トラバースするための補助変数が必要です
  46. HeroNode temp = head.next ;
  47. while ( temp != null ) {
  48. //終了かどうか判断する
  49. // 出力ノード情報
  50. System.out.println ( temp ) ;
  51. //温度戻す
  52. temp = temp . next ;
  53. }
  54. }
  55. }
  56.  
  57. //HeroNodeを定義します。各HeroNodeオブジェクトはノードです
  58. クラスHeroNode {
  59. 公共 整数 いいえ;
  60. パブリック文字列;
  61. パブリック文字列ニックネーム;
  62. public HeroNode next ;//次のノードを指す
  63.  
  64. //コンストラクタ
  65. パブリックHeroNode( int   no 、String name 、String nickName) {
  66. this.no =いいえ;
  67. this.name =名前;
  68. this.nickName = ニックネーム;
  69. }
  70.  
  71. パブリックHeroNode getNext() {
  72. 戻る ;
  73. }
  74.  
  75. パブリックvoid setNext(HeroNode next ) {
  76. this.next =次へ;
  77. }
  78.  
  79. @オーバーライド
  80. パブリック文字列toString() {
  81. 戻る  「ヒーローノード{" +
  82. 「いいえ=」 +いいえ+
  83. ", 名前='" +名前+ '\ '' +
  84. ", ニックネーム='" + ニックネーム + '\ '' +
  85. '}' ;
  86. }
  87. }
  88. /*
  89. HeroNode{ no =3、 name = 'Wu Yong' 、 nickName= 'Smart Star' }
  90. HeroNode{ no =2、 name = 'Lu Junyi' 、 nickName= 'Yu Qilin' }
  91. HeroNode{ no =4、 name = 'Lin Chong' 、 nickName= 'Leopard Head' }
  92. HeroNode{ no =1、 name = 'Song Jiang' 、 nickName= 'Timely Rain' }
  93. */

上記のリンク リストの実装では、ヒーローを追加するときに番号で並べ替えられないことがわかります。ヒーローを挿入するときに番号で並べ替えるように add メソッドを書き直してみましょう。

  1. パッケージ com.structures.linkedlist;
  2.  
  3. パブリッククラスSingleLinkedListDemo {
  4. 公共 静的void main(String[] args) {
  5. HeroNode heroNode1 = new HeroNode(1, "Song Jiang" , "Timely Rain" );
  6. HeroNode heroNode2 = new HeroNode(2, "Lu Junyi" , "Yu Qilin" );
  7. HeroNode heroNode3 = new HeroNode(3, "Wu Yong" , "Zhi Duo Xing" );
  8. HeroNode heroNode4 = new HeroNode(4, "Lin Chong" , "Leopard Head" );
  9. シングルリンクリスト singleLinkedList = 新しいシングルリンクリスト();
  10. 単一のLinkedList.addByNo(heroNode3);
  11. 単一のLinkedList.addByNo(heroNode2);
  12. 単一のLinkedList.addByNo(heroNode4);
  13. 単一のLinkedList.addByNo(heroNode1);
  14. シングルリンクリスト.list();
  15. }
  16. }
  17.  
  18. //ヒーローを管理するためにSingleLinkedListを定義する
  19. クラスSingleLinkedList {
  20. //まずヘッドノードを初期化します。ヘッドノードは移動できず、将来のトラバーサルに使用されます。
  21. プライベートHeroNodeヘッド = 新しいHeroNode(0, "" , "" );
  22.  
  23. // 単一リンクリストにノードを追加する
  24. // アイデア: 数字の順序を考慮しない場合
  25. //1. 現在のリンクリストの最後のノードを見つける
  26. //2. 最後のノードの次のフィールドを新しいノードにポイントする
  27. パブリックvoid追加(HeroNode ノード) {
  28. //ヘッドノードは移動できないため、補助的なトラバーサルテンポが必要です 
  29. HeroNode temp = ヘッド;
  30. //リンクリストを走査して最後の
  31. while ( temp . next != null ) {
  32. // リンクリストの末尾を見つける
  33. // tempが見つからない場合は戻る
  34. temp = temp . next ;
  35. }
  36. temp . next = ノード;
  37. }
  38.  
  39. //ヒーローを追加する2番目の方法は、ヒーローを追加するときに、ランキングに従って指定された位置にヒーローを挿入します
  40. //そのような順位がある場合、追加は失敗し、プロンプトが表示されます
  41. パブリックvoid addByNo(HeroNode heroNode) {
  42. //ヘッドノードは移動できないため、補助的なトラバーサルテンポが必要です 
  43. //これは単一のリンクリストなので、探している一時ノードは追加された位置の前のノードです。そうでなければ追加できません。
  44. HeroNode temp = ヘッド;
  45. ブール型フラグ = false ; // 追加された番号が存在するかどうかを示します。デフォルトはfalseです 
  46. )の間{
  47. if ( temp . next == null ) {
  48. 壊す;
  49. }
  50. if ( temp . next . no > heroNode. no ) { //位置が見つかったら、 tempの後に挿入します
  51. 壊す;
  52. }そうでない場合 ( temp . next . no == heroNode . no ) {
  53. //番号はすでに存在します
  54. フラグ = true ;
  55. 壊す;
  56. }
  57. temp = temp . next ;
  58. }
  59. if (フラグ) {
  60. System.out.printf ( "挿入するヒーロー番号%dはすでに存在するため、追加できません\n" heroNode.no );
  61. }それ以外{
  62. //リンクリストの後ろに挿入temp
  63. ヒーローノード次のコード
  64. temp . next = heroNode;
  65. }
  66. }
  67.  
  68. //リンクリストを表示する [トラバーサル]
  69. パブリックボイドリスト(){
  70. // リンクリストが空かどうか確認する
  71. head.next == nullの場合){
  72. System.out.println ( "リンクリストは空です" );
  73. }
  74. //ヘッドノードは移動できないため、トラバースするための補助変数が必要です
  75. HeroNode temp = head.next ;
  76. while ( temp != null ) {
  77. //終了かどうか判断する
  78. // 出力ノード情報
  79. System.out.println ( temp ) ;
  80. //温度戻す
  81. temp = temp . next ;
  82. }
  83. }
  84. }
  85.  
  86. //HeroNodeを定義します。各HeroNodeオブジェクトはノードです
  87. クラスHeroNode {
  88. 公共 整数 いいえ;
  89. パブリック文字列;
  90. パブリック文字列ニックネーム;
  91. public HeroNode next ;//次のノードを指す
  92.  
  93. //コンストラクタ
  94. パブリックHeroNode( int   no 、String name 、String nickName) {
  95. this.no =いいえ;
  96. this.name =名前;
  97. this.nickName = ニックネーム;
  98. }
  99.  
  100. パブリックHeroNode getNext() {
  101. 戻る ;
  102. }
  103.  
  104. パブリックvoid setNext(HeroNode next ) {
  105. this.next =次へ;
  106. }
  107.  
  108. @オーバーライド
  109. パブリック文字列toString() {
  110. 戻る  「ヒーローノード{" +
  111. 「いいえ=」 +いいえ+
  112. ", 名前='" +名前+ '\ '' +
  113. ", ニックネーム='" + ニックネーム + '\ '' +
  114. '}' ;
  115. }
  116. }
  117. /*
  118. HeroNode{ no =1、 name = 'Song Jiang' 、 nickName= 'Timely Rain' }
  119. HeroNode{ no =2、 name = 'Lu Junyi' 、nickName= 'Yu Qilin' }
  120. HeroNode{ no =3、 name = 'Wu Yong' 、 nickName= 'Smart Star' }
  121. HeroNode{ no =4、 name = 'Lin Chong' 、nickName= 'Leopard Head' }
  122. */

機能を再度改善し、ノードを変更する機能を追加

  1. //番号に応じてノード情報を変更します。つまり、番号変更できません。
  2. パブリックvoid更新(HeroNode heroNode) {
  3. //空かどうかを判定する
  4. head.next == nullの場合){
  5. System.out.println ( "リンクリストは空です" ) ;
  6. }
  7. //番号に従って変更が必要なノードを検索します
  8. HeroNode temp = head.next ;
  9. boolean flag = false ; // ノードが見つかったかどうかを示します
  10. )の間{
  11. 温度nullの場合
  12. 壊す;
  13. }
  14. if ( temp . no == heroNode . no ) {
  15. フラグ = true ;
  16. 壊す;
  17. }
  18. temp = temp . next ;
  19. }
  20. if (フラグ) {
  21. temp.name = heroNode.name ;
  22. temp.nickName = heroNode.nickName;
  23. }それ以外{
  24. System.out.printf ( "ノード番号%d見つからないため、変更できません\n" 、heroNode.no );
  25. }
  26. }

再度機能を改善し、ノード削除機能を追加

  1. //ノードを削除する
  2. パブリックvoid 削除(HeroNode heroNode) {
  3. //空かどうかを判定する
  4. head.next == nullの場合){
  5. System.out.println ( "リンクリストは空です" ) ;
  6. }
  7. HeroNode temp = head.next ;
  8. boolean flag = false ; //削除するポイントが見つかったかどうかを識別します
  9. )の間{
  10. 温度nullの場合
  11. 壊す;
  12. }
  13. if ( temp . next . no == heroNode . no ) {
  14. フラグ = true ;
  15. 壊す;
  16. }
  17. temp = temp . next ;
  18. }
  19. if (フラグ) {
  20. temp.next = temp.next.next ;
  21. }それ以外{
  22. System.out.printf ( "ノード番号%d削除できません、\n" 、heroNode.no );
  23. }
  24. }

機能を再度改良し、単一のリンクリスト内の有効なノードの数をカウントする機能を追加します

  1. /**
  2. * ヘッドノードを除く、単一のリンクリスト内の有効なノードの数を取得します。
  3. * @param head リンクリストの先頭ノード
  4. * @return有効なノードの数
  5. */
  6. 公共 静的  int getLength(HeroNode のヘッド) {
  7. head.next == nullの場合){
  8. 0を返します
  9. }
  10. 整数 カウント= 0;
  11. HeroNode temp = head.next ;
  12. while ( temp . next != null ) {
  13. カウント++;
  14. temp = temp . next ;
  15. }
  16. 戻る カウント;
  17. }

関数を再度改良し、単連結リストのK番目最後のノードを見つける関数を追加します。

  1. /**
  2. * 単方向リンクリストの K 番目の最後のノードを見つける [Sina のインタビューの質問]
  3. * アイデア:
  4. * 1. まずリンクリストを最初から最後まで走査して、リンクリストの合計の長さを取得します。
  5. * 2.サイズを取得した後、最初のリンクリストから(サイズ-インデックス)まで走査して、
  6. *
  7. * @param ヘッド
  8. * @param indexは最後のノードインデックスを示します
  9. * @戻る 
  10. */
  11. 公共 静的HeroNode findLastIndexNode(HeroNode head, int  索引) {
  12. head.next == nullの場合){
  13. 戻る ヌル;
  14. }
  15. 整数 サイズ= getLength(head);
  16. if (インデックス<= 0 ||インデックス>サイズ) {
  17. 戻る ヌル;
  18. }
  19. HeroNode temp = head.next ;
  20. for ( int i = 0; i < (サイズ-インデックス); i++) {
  21. temp = temp . next ;
  22. }
  23. 戻る 温度;
  24. }

関数を再度改良し、単一リンクリスト反転関数を追加する

  1. /**
  2. * 逆リンクリスト [Tencent 面接の質問]
  3. * アイデア:
  4. * 1. まず、reverseHead = new HeroHead(); を定義します。
  5. * 2. 元のリンク リストを最初から最後まで走査し、走査後に各ノードを取り出して、新しいリンク リストの先頭に配置します。
  6. * 3.元のリンクリストのhead.next = riverHead.next ;
  7. */
  8. 公共 静的voidリバースリスト(HeroNodeヘッド) {
  9. もし( head.next == null || head.next.next == null ) {
  10. 戻る;
  11. }
  12. HeroNode curr = head.next ;
  13. HeroNode next = null ; //現在のノードの次のノードを指す [curr]
  14. HeroNode を逆にすると、新しい HeroNode (0, "" , "" ) が作成されます。
  15.  
  16. while (curr != null ) {
  17. next = curr.next ;// currノードの次のノードを一時的に保存します
  18. curr.next = riverHead.next ; // curr の次のノードを新しいリンクリスト先頭にポイントします
  19. riverHead.next = curr; // currを新しいリンクリストに接続します
  20. curr = next ; // curr を後ろに移動
  21. }
  22. head.next =逆Head.next ;
  23. }

再度機能を改良し、末尾から先頭まで単一のリンクリストを印刷する機能を追加します

  1. /**
  2. * スタックを使用して逆順に印刷する [Baidu の面接の質問]
  3. */
  4. 公共 静的void逆印刷(HeroNodeヘッド) {
  5. head.next == nullの場合){
  6. 戻る;
  7. }
  8. Stack<HeroNode> heroNodes = 新しい Stack<HeroNode>();
  9. HeroNode temp = head.next ;
  10. while ( temp != null ) {
  11. heroNodes.add ( temp ) ;
  12. temp = temp . next ;
  13. }
  14. ( heroNodes.size () > 0)の場合
  15. System.out.println (heroNodes.pop()) ;
  16. }
  17. }

【編集者のおすすめ】

  1. いいですね、上司からシンプルなワークフロー エンジンを開発するように言われました...
  2. Windows 10 は世界を揺るがす変化をもたらします!今年最初のアップデートが来ました
  3. 2021年に注目すべき6つのサイバーセキュリティトレンド
  4. 近年の Windows 10 における最大の改善点! Windows 10 21H2 新機能プレビュー
  5. Xiao Aiは本当にPC版をリリースしたのか?コンピュータ版のXiao Aiを体験してみましょう

<<:  ザッカーバーグの45分間の詳細なインタビュー:今後10年間のVRと脳コンピューターインターフェースへの野望を明らかにする

>>:  人工知能の急速な発展により、どのようなビジネス分野に浸透しているのでしょうか?テレマーケティングの将来はどうなるのでしょうか?

ブログ    

推薦する

この世界規模の問題に対して、ドローンはどれほどの助けとなるのでしょうか?

火事を起こすのは簡単ですが、消すのは難しいです。これは世界的な問題ですが、これを効果的に予防し、迅速...

...

産業用ロボットの 4 つのプログラミング技術のうち、いくつ知っていますか?

1. 概要現在、ロボットは溶接、組み立て、ハンドリング、塗装、研磨などの分野で広く利用されており、...

...

畳み込みニューラルネットワークのパフォーマンス最適化

導入畳み込みはニューラル ネットワークのコア計算の 1 つです。コンピューター ビジョンにおける畳み...

人工知能は実際のデータセットを「放棄」するのか?

現在、人工知能技術は、顔認識、音声認識、仮想デジタルヒューマンなど、私たちの日常生活のあらゆる側面に...

機械が人間に取って代わるというのは空想ではありません。最初に影響を受けるのは 3 つの職業です。油断しないでください。

科学技術の継続的な発展により、多くの業界で「ロボット」が使用され、効率が向上するだけでなく、人件費も...

...

既存のビッグデータ技術を使用して機械学習プラットフォームを構築する方法

[[210160]]機械はどのように学習するのでしょうか?人間の脳は継続的に経験を蓄積する能力があり...

人工知能と医師が出会ったら何が起こるかを伝える7つの短編物語

[[187416]] Huxiu 注: この記事は、4 月 3 日に The New Yorker ...

一般的な顔認識システムの端末設置と配線の包括的なレビュー

顔認識端末は人事管理や出勤簿、人通りの多いセキュリティチェックポイントなどで広く利用されている。今年...

検討すべき5つのスマートホームテクノロジー

今日でも、ほとんどの人はスマートホームテクノロジーを手の届かない贅沢品と見なしています。しかし、家庭...

Alibaba Cloudが「Tongyi Lingma」AIプログラミングツールをリリース、VS CodeやJetBrainsなどの主流IDEをサポート

11月1日、アリババクラウドは「Tongyi Lingma」というAIプログラミングツールをリリース...