私は単一のリンクリストを破棄しようとしています。最初は、destroy関数のコードは次のようになっています。
void destroy_list_v0 (SLINK *list)
{
SLINK ptr = *list;
while (NULL != *list)
{
ptr = *list;
*list = (*list)->next;
free (ptr);
}
}
関数v0は完璧に機能します。ここに出力があります。
Input a number for length of the link.
init_start.
init_end & traverset_start.
The 0th element is 0.
The 1st element is 5.
The 2nd element is 93.
The 3rd element is 92.
The 4th element is 70.
The 5th element is 92.
traverse_end & destroy_start.
destroy_end & traverse_start.
traverse_end.
All operations done.
次に、シングルポンターで十分だと思ったので、関数をシングルポインターバージョンに調整します。
void destroy_list_v1 (SLINK list)
{
SLINK ptr = list;
while (NULL != list)
{
ptr = list;
list = list->next;
free (ptr);
}
}
v1の出力は次のとおりです。
Input a number for length of the link.
init_start.
init_end & traverset_start.
The 0th element is 0.
The 1st element is 27.
The 2nd element is 38.
The 3rd element is 20.
The 4th element is 66.
The 5th element is 30.
traverse_end & destroy_start.
destroy_end & traverse_start.
The 0th element is 0.
The 1st element is 32759808.
The 2nd element is 32759968.
The 3rd element is 32759936.
The 4th element is 32759904.
The 5th element is 32759872.
traverse_end.
All operations done.
破棄機能が正常に機能していることを確認するために、破棄された後にリンクリストをトラバースします。すべてのノードの値が変更され、不確定であるにもかかわらず、リストを読み取ることができることがわかりました(v0の場合は読み取ることができませんでした)。v0が実行された後、リストのポインターはNULLを指していると思いましたが、v1が実行された後も、元のアドレスを指します。このアイデアをテストするために、v0をv2に調整します。
void destroy_list_v2 (SLINK *list)
{
SLINK p_list = *list;
SLINK ptr = *list;
while (NULL != *p_list)
{
ptr = *p_list;
p_list = p_list->next;
free (ptr);
}
}
v2の出力は次のとおりです。
Input a number for length of the link.
init_start.
init_end & traverset_start.
The 0th element is 0.
The 1st element is 76.
The 2nd element is 53.
The 3rd element is 80.
The 4th element is 31.
The 5th element is 97.
traverse_end & destroy_start.
destroy_end & traverse_start.
The 0th element is 0.
The 1st element is 13860864.
The 2nd element is 13861024.
The 3rd element is 13860992.
The 4th element is 13860960.
The 5th element is 13860928.
traverse_end.
All operations done.
私の分析は正しいと思いますが、それは新しい疑問につながります。
ノード構造体はここにあります:
typedef struct tag_node
{
int elem;
struct tag_node *next;
}NODE, *SLINK; //SLINK means SINGLE LINK
2つの質問があります:
1:ポインタ'next'は、現在のポインタが指すメモリ空間に格納されます。現在のノードを解放した後、ポインタ'next'のメモリ空間をまだ読み取ることができるのはなぜですか。ポインタ「次へ」はまだ生きていますか?この質問があるのは、v1またはv2が実行された後、読み取ることができるのはヘッダーノードのみである必要があると考えたためです。
2:v1またはv2が実行された後、v1およびv2がリスト全体を破棄するのに、なぜヘッダーの値がまだ残っているのですか?不定の数字に変わったのは1日から5日くらいのはずだと思いました。
これがコード全体であり、環境はDebian、clangです:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define i_track(n) printf ("The %s's is %d.\n", #n, (n))
#define s_track(n) printf ("%s.\n", #n);
typedef struct tag_node
{
int elem;
struct tag_node *next;
}NODE, *SLINK; //SLINK means SINGLE LINK
void node_track (SLINK list);
NODE *node_generate (void);
SLINK init_list (int len);
SLINK locate_cur (SLINK list, int target_elem);
void insert_node (SLINK *list, int new_elem, int tag_elem);
SLINK traverse_list (SLINK list);
void clear_list (SLINK list);
void destroy_list_v0 (SLINK *list);
void destroy_list_v1 (SLINK list);
void destroy_list_v2 (SLINK *list);
void list_info (SLINK list, int node_elem);
int main (int argc, char *argv[])
{
int len;
SLINK list;
printf ("Input a number for length of the link.\n");
scanf ("%d", &len);
s_track(init_start);
list = init_list (len);
s_track(init_end & traverset_start);
traverse_list (list);
s_track(traverse_end & destroy_start);
// destroy_list_v0 (&list);
// destroy_list_v1 (list);
destroy_list_v2 (&list);
s_track(destroy_end & traverse_start);
traverse_list (list);
s_track(traverse_end);
s_track(All operations done);
return EXIT_SUCCESS;
} /* ---------- end of function main ---------- */
NODE *node_generate (void)
{
NODE *new_node = malloc (sizeof (NODE));
if (NULL == new_node)
{
printf ("ERROR: malloc failed.\n");
exit (EXIT_FAILURE);
}
memset (new_node, 0, sizeof(NODE));
return new_node;
}
SLINK locate_cur (SLINK list, int target_elem)
{
NODE *prev, *cur;
prev = node_generate ();
cur = node_generate ();
for (prev = list, cur = list->next; NULL != cur && target_elem != cur->elem; prev = cur, cur = cur->next)
;
return cur;
}
void insert_node (SLINK *list, int new_elem, int tag_elem)
{
NODE *new_node = node_generate ();
NODE *cur = *list;
new_node->elem = new_elem;
if ((int)NULL == tag_elem)
{
new_node->next = (*list)->next;
(*list)->next = new_node;
}
else
{
*list = locate_cur (cur, tag_elem);
new_node->next = (*list)->next;
(*list)->next = new_node;
}
}
SLINK init_list (int len)
{
SLINK header = node_generate ();
srand ((unsigned) time(0));
int elem;
for (int i = 0; i < len; i++)
{
elem = rand () % 100;
if (4 == elem / 10)
{
elem = elem + 50;
}
if (4 == elem % 10)
{
elem = elem + 5;
}
if (0 == elem % 100)
{
elem = elem + 999;
}
insert_node (&header, elem, (int)NULL);
}
return header;
}
void clear_list (SLINK list)
{
for (SLINK cur = list->next; NULL != cur; )
{
cur = cur->next;
free (list->next);
list->next = cur;
}
}
void destroy_list_v0 (SLINK *list)
{
SLINK ptr = *list;
while (NULL != *list)
{
ptr = *list;
*list = (*list)->next;
free (ptr);
}
}
void destroy_list_v1 (SLINK list)
{
SLINK ptr = list;
while (NULL != list)
{
ptr = list;
list = list->next;
free (ptr);
}
}
void destroy_list_v2 (SLINK *list)
{
SLINK p_list = *list;
SLINK ptr = *list;
while (NULL != p_list)
{
ptr = p_list;
p_list = p_list->next;
free (ptr);
}
}
SLINK traverse_list (SLINK list)
{
SLINK ptr = list;
for (int node_num = 0; ptr != NULL; ptr = ptr->next)
{
list_info (ptr, node_num);
++node_num;
}
return list;
}
void list_info (SLINK list, int node_num)
{
if (1 == node_num % 10 && 11 != node_num)
{
printf ("The %dst element is %d.\n", node_num, list->elem);
}
else if (2 == node_num % 10 && 12 != node_num)
{
printf ("The %dnd element is %d.\n", node_num, list->elem);
}
else if (3 == node_num % 10 && 13 != node_num)
{
printf ("The %drd element is %d.\n", node_num, list->elem);
}
else
{
printf ("The %dth element is %d.\n", node_num, list->elem);
}
}
void node_track (NODE *flag)
{
printf ("The flag element is %d.\n", flag->elem);
}