質問するログイン新規登録

回答編集履歴

2

ソースファイルを追加

2019/05/16 13:09

投稿

Bull
Bull

スコア986

answer CHANGED
@@ -45,4 +45,109 @@
45
45
  なので、効率も悪いので挿入ソートはやめた方がいいかもしれません。
46
46
 
47
47
  余談ですがバブルソートや選択ソートでしたら順方向だけでもできます。
48
- 更に余談、以前にお遊びで単方向リストを逆方向に辿る処理を実装したことがあります。その時は再帰関数で実装したので、ノードの個数分再帰が深くなります。速度も遅いしあまり実用的ではないですね。
48
+ 更に余談、以前にお遊びで単方向リストを逆方向に辿る処理を実装したことがあります。その時は再帰関数で実装したので、ノードの個数分再帰が深くなります。速度も遅いしあまり実用的ではないですね。
49
+
50
+ ---
51
+ 度々追加ですいません。
52
+ 逆順にこだわって実装してみました。
53
+ あまり実用的ではないですし、再帰呼び出ししているので要素数が多いとダメですけど。
54
+ ```c
55
+ #include <stdio.h>
56
+ #include <stdlib.h>
57
+
58
+ typedef struct _cell {
59
+ int element;
60
+ struct _cell *next;
61
+ }cell;
62
+
63
+ typedef struct _list {
64
+ cell *head;
65
+ }list;
66
+
67
+ list* create() {
68
+ list *L = (list *)malloc(sizeof(list));
69
+ L->head = (cell *)malloc(sizeof(cell));
70
+ L->head->next = NULL;
71
+ L->head->element = -1;
72
+ return L;
73
+ }
74
+
75
+ void addFirst(list *L, int element) {
76
+ cell *add = (cell *)malloc(sizeof(cell));
77
+ add->element = element;
78
+ add->next = L->head->next;
79
+ L->head->next = add;
80
+ }
81
+
82
+ void del(list *L, int element) {
83
+ cell *ptr = L->head->next;
84
+ cell *prev = L->head;
85
+ while (ptr != NULL) {
86
+ if (ptr->element == element) {
87
+ prev->next = ptr->next;
88
+ } else {
89
+ prev = ptr;
90
+ }
91
+ ptr = ptr->next;
92
+ }
93
+ }
94
+
95
+ void search(list *L, int element) {
96
+ cell *ptr = L->head->next;
97
+ while (ptr != NULL) {
98
+ if (ptr->element == element) {
99
+ printf("Found! : %d\n", ptr->element);
100
+ }
101
+ ptr = ptr->next;
102
+
103
+ }
104
+ }
105
+
106
+
107
+ void print(list *L) {
108
+ cell *ptr = L->head->next;
109
+ while (ptr != NULL) {
110
+ printf("%d\n", ptr->element);
111
+ ptr = ptr->next;
112
+ }
113
+ }
114
+
115
+ void sort_sub(cell *p)
116
+ {
117
+ if (p) {
118
+ sort_sub(p->next); //再帰呼び出しでリストを逆順に辿る
119
+
120
+ int temp = p->element; //データを保存
121
+ while (p->next) {
122
+ if (temp > p->next->element) { //挿入位置を探す
123
+ p->element = p->next->element; //データをずらす
124
+ } else {
125
+ break;
126
+ }
127
+
128
+ p = p->next; //次の要素
129
+ }
130
+
131
+ p->element = temp; //挿入する
132
+ }
133
+ }
134
+
135
+ void sort(list *L)
136
+ {
137
+ sort_sub(L->head->next);
138
+ }
139
+
140
+ int main(void) {
141
+ list *L = create();
142
+ addFirst(L, 1);
143
+ addFirst(L, 2);
144
+ addFirst(L, 3);
145
+ addFirst(L, 4);
146
+ addFirst(L, 5);
147
+ print(L);
148
+ sort(L);
149
+ print(L);
150
+
151
+ return 0;
152
+ }
153
+ ```

1

質問に超えていなかったので補足説明を追加

2019/05/16 13:09

投稿

Bull
Bull

スコア986

answer CHANGED
@@ -36,4 +36,13 @@
36
36
 
37
37
  L->head->next = new_list; // ソート済みのリスト
38
38
  }
39
- ```
39
+ ```
40
+ ---
41
+ 質問の答えになってなかったので、補足します。
42
+
43
+ 何故ソートできないか?
44
+ 配列の場合を考えてみれば分りますが、挿入ソートにするにはリストを順方向と逆方向に走査する必要があります。ご提示のプログラムではそれが出来ていません。単方向リストを逆方向に辿るのは出来なくはないですが、かなり手間のかかる作業になります。
45
+ なので、効率も悪いので挿入ソートはやめた方がいいかもしれません。
46
+
47
+ 余談ですがバブルソートや選択ソートでしたら順方向だけでもできます。
48
+ 更に余談、以前にお遊びで単方向リストを逆方向に辿る処理を実装したことがあります。その時は再帰関数で実装したので、ノードの個数分再帰が深くなります。速度も遅いしあまり実用的ではないですね。