【问题标题】:bubble sort with link list带链表的冒泡排序
【发布时间】:2012-11-19 04:09:00
【问题描述】:

我是 C 大一新生,现在学习链接列表。当我对链表进行冒泡排序时,出现段错误,GDB指向函数bubble(),i = ptr->elem。我不知道这是什么原因。请帮忙弄清楚。

`

#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; 

void  node_track (SLINK list);
NODE *node_generate (void);
void init_list (SLINK *header, 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 list_info (SLINK list, int node_elem);
void bubble (SLINK list);
void swap (int *a, int *b);

int main (int argc, char *argv[])
{
int len;
SLINK list = node_generate ();
printf ("Input a number for length of the link.\n");
scanf ("%d", &len);
s_track(init_start.);
init_list (&list, len);
s_track(init_end.);
traverse_list (list);
bubble (list);

return EXIT_SUCCESS;
}   /* ----------  end of function main  ---------- */          

NODE *node_generate (void) /* generate a node */
{
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;
}

void insert_node (SLINK *list, int new_elem, int tag_elem)
/* insert a node */
{
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;
}
}

void init_list (SLINK *header, int len)
/* generate a linked-list and assign it*/
{
srand ((unsigned) time(0));
int elem;
for (int i = 0; i < len; i++)
    /* skip number 4 since I dislike it */
    {
        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);  
    }
}

SLINK traverse_list (SLINK list)
/*traverse list */
{
SLINK ptr = list;
for (int node_num = 0; ptr != NULL; ptr = ptr->next)
{
    ++node_num;
    list_info (ptr, node_num);
}
return list;
}

void list_info (SLINK list, int node_num)
/* used for traversed_list () */
{
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);
}
}

SLINK locate_cur (SLINK list, int target_elem)
/* locate previous of a node */
{
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 node_track (NODE *flag)
{
printf ("The flag element is %d.\n", flag->elem);
}

void bubble (SLINK list) /* bubble sort */
{
s_track(bubble_start);
list = list->next;
SLINK ptr, header;
ptr = list; /*GDB point to here*/
int i =0, j = 0;
for (; NULL != list; list = list->next)
{
    for (ptr = list; NULL != ptr; ptr = ptr->next);
    {
        j = list->elem;
        i = ptr->elem;
    //  if (ptr->elem > list->elem)
        if (i > j)
            swap (&(ptr->elem), &(list->elem));
    }
}
s_track(bubble_end);
}

void swap (int *a, int *b)
{
*a = (*a)^(*b);
*b = (*a)^(*b);
*a = (*a)^(*b);
}

`

【问题讨论】:

  • 基于异或的交换是不明智的。开头的#define 缺少#
  • 您可以使用calloc() 而不是malloc(),后跟memset()。测试if ((int)NULL == tag_elem)很好奇;但是'tag_elem'的目的充其量只是好奇,而且我很难弄清楚它的意义,特别是因为当从init_list() 中调用insert_node 时它总是'NULL'。

标签: c linked-list


【解决方案1】:

init_list() 中的tag_elem 的用途非常不清楚。我修改了代码以消除该变量,然后运行它并将 5 指定为输入值。它给出了:

Input a number for length of the link.
5
init_start..
init_end..
The 1st element is 0.
The 2nd element is 12.
The 3rd element is 8.
The 4th element is 99.
The 5th element is 7.
The 6th element is 63.
bubble_start.
Segmentation fault: 11

为什么在请求 5 个项目时打印了 6 个项目?重复执行时,第一个元素中的值始终为 0(重复 3 次)。

这个问题可以通过修改traverse_list()来解决:

SLINK traverse_list(SLINK list)
{
    assert(list != 0); 
    SLINK ptr = list->next;
    for (int node_num = 0; ptr != NULL; ptr = ptr->next)
        list_info(ptr, ++node_num);
    return list;
}

有趣的是,bubble() 中的代码已经跳过了列表中的第一项。

但是bubble()中的内循环有一个错误:

for (ptr = list; NULL != ptr; ptr = ptr->next);
{
    j = list->elem;
    i = ptr->elem;
//  if (ptr->elem > list->elem)
    if (i > j)
        swap (&(ptr->elem), &(list->elem));
}

如果你写成这样可能会更容易看到:

for (ptr = list; NULL != ptr; ptr = ptr->next)
    ;
{
    j = list->elem;
    i = ptr->elem;  // When this is executed, ptr == NULL!
    if (i > j)
        swap (&(ptr->elem), &(list->elem));
}

你不想要那个分号。修复后,代码运行正常:

Input a number for length of the link.
5
init start.
init end.
The 1st element is 12.
The 2nd element is 19.
The 3rd element is 99.
The 4th element is 92.
The 5th element is 28.
traverse 1 end.
bubble_start.
bubble_end.
sort end.
The 1st element is 99.
The 2nd element is 92.
The 3rd element is 28.
The 4th element is 19.
The 5th element is 12.
traverse 2 end.

显然,一组稍作修改的诊断打印,但数据是按降序排列的。看起来它也适用于更大的场景;我尝试了 55 没有崩溃,数据中有一些重复,并且输出按降序排序。

【讨论】:

  • 感谢您的大力帮助。我已经在您的帮助下通过删除分号修复了它。一个愚蠢的错误。对于init_list(),因为我不喜欢数字4,所以函数看起来很奇怪,不清楚。我知道第一个节点的值为0,这不是错误,对于原始函数,节点的元素是一个联合,它就像这样:'union {char *s; int n;}',第一个节点是由一个字符串分配的,所以在bubble()中,它被跳过了。非常感谢。
猜你喜欢
  • 1970-01-01
  • 2011-09-04
  • 1970-01-01
  • 2012-09-29
  • 1970-01-01
  • 2012-07-19
相关资源
最近更新 更多