【问题标题】:why replacing *s with **s in SortedMerge() causes the program to crash?为什么在 SortedMerge() 中用 **s 替换 *s 会导致程序崩溃?
【发布时间】:2014-05-29 05:05:11
【问题描述】:

在调试的时候发现用*s替换**s可以让程序正常运行,但是我不明白为什么**s会导致SortedMerge()函数出错,请帮忙

#include<stdio.h>
#include<stdlib.h>

/* Link list node */
struct node
{
    int data;
    struct node* next;
};

/* function prototypes */
struct node* SortedMerge(struct node* a, struct node* b);
void FrontBackSplit(struct node* source,
          struct node** frontRef, struct node** backRef);

/* sorts the linked list by changing next pointers (not data) */
void MergeSort(struct node **head)
{
    /*if list empty or contains one element, return head*/
    if((*head==NULL)||((*head)->next)==NULL)
        return *head;

    /*if control here, implies, atleast 2 nodes present in ll*/
    struct node* a=NULL;
    struct node* b=NULL;
    FrontBackSplit(*head,&a,&b);

    MergeSort(&a);
    MergeSort(&b);

    *head=SortedMerge(a,b);

}

/* See http://geeksforgeeks.org/?p=3622 for details of this
   function */
struct node* SortedMerge(struct node* first,struct node* second)
{
    if((first==NULL)&&(second==NULL))
        return NULL;
    if(first==NULL)
        return (second);
    if(second==NULL)
    {
        return (first);
    }
    /*first and second list both have elements*/

    struct node **s=NULL;
    struct node *z=NULL;

    while((first!=NULL)&&(second!=NULL))
    {
        if(*s==NULL)
        {
            *s = malloc(sizeof(struct node));
            z = *s;
        }
        else
        {
            z->next = malloc(sizeof(struct node));
            z = z->next;
        }

        if(first->data<=second->data)
        {
            z->data = first->data;
            first = first->next;
        }
        else
        {
            z->data = second ->data;
            second = second ->next;
        }
    }
    while(first!=NULL)
    {
            z->next = malloc(sizeof(struct node));
            z = z->next;

            z->data = first->data;
            first = first->next;
    }
    while(second!=NULL)
    {
            z->next = malloc(sizeof(struct node));
            z = z->next;

            z->data = second->data;
            second = second->next;
    }
    z->next=NULL;
    return *s;
}

/* UTILITY FUNCTIONS */
/* Split the nodes of the given list into front and back halves,
     and return the two lists using the reference parameters.
     If the length is odd, the extra node should go in the front list.
     Uses the fast/slow pointer strategy.  */
void FrontBackSplit(struct node* head,struct node **first,struct node **last)
{
    struct node *slow_ptr=head;
    struct node *fast_ptr=head->next;
    if((head==NULL)||(head->next==NULL))
    {
        *first=head;
        *last=NULL;
        return;
    }

    while((fast_ptr!=NULL)&&(fast_ptr->next!=NULL))
    {
        fast_ptr=fast_ptr->next->next;
        slow_ptr=slow_ptr->next;
    }
    *last=slow_ptr->next;
    slow_ptr->next=NULL;
    *first=head;
    return;
}

/* UTILITY FUNCTIONS */
/* Split the nodes of the given list into front and back halves,
     and return the two lists using the reference parameters.
     If the length is odd, the extra node should go in the front list.
     Uses the fast/slow pointer strategy.  */


/* Function to print nodes in a given linked list */
void printList(struct node *node)
{
  while(node!=NULL)
  {
   printf("%d ", node->data);
   node = node->next;
  }
}

/* Function to insert a node at the beginging of the linked list */
void push(struct node** head_ref, int new_data)
{
  /* allocate node */
  struct node* new_node =
            (struct node*) malloc(sizeof(struct node));

  /* put in the data  */
  new_node->data  = new_data;

  /* link the old list off the new node */
  new_node->next = (*head_ref);

  /* move the head to point to the new node */
  (*head_ref)    = new_node;
}

/* Drier program to test above functions*/
int main()
{
  /* Start with the empty list */
  struct node* res = NULL;
  struct node* a = NULL;

  /* Let us create a unsorted linked lists to test the functions
   Created lists shall be a: 2->3->20->5->10->15 */
  push(&a, 15);
  push(&a, 10);
  push(&a, 5);
  push(&a, 20);
  push(&a, 3);
  push(&a, 2);

  /* Sort the above created Linked List */
  MergeSort(&a);

  printf("\n Sorted Linked List is: \n");
  printList(a);

  getchar();
  return 0;
}

这是我替换的工作 SortedMerge() 函数..

struct node* SortedMerge(struct node* a, struct node* b)
{
  struct node* result = NULL;

  /* Base cases */
  if (a == NULL)
     return(b);
  else if (b==NULL)
     return(a);

  /* Pick either a or b, and recur */
  if (a->data <= b->data)
  {
     result = a;
     result->next = SortedMerge(a->next, b);
  }
  else
  {
     result = b;
     result->next = SortedMerge(a, b->next);
  }
  return(result);
}

【问题讨论】:

  • 没有足够的代码让正在运行的程序重现问题。代码太多,无法阅读。请尽量减少到您认为可能存在问题的地方,或者提供可编译的程序。
  • 您还应该尝试在调试器中逐步执行程序,以查看发生无限循环的位置。
  • 为什么不试试调试呢?
  • 当然,我在寻找错误时打破了我的头,超过 2 小时,我不能这就是我在这里发布它的原因。
  • @merlin2011 我已经放了可编译的代码,请看更新的代码

标签: c linked-list mergesort


【解决方案1】:

split 函数将列表分成两部分;没有分配或释放内存。 (其实之后*head == *a,不过没关系)。

merge 函数应该是 split 的逆函数:将两个部分组合成一个列表,无需分配或释放。但是它包含malloc 语句。这一定是一个错误;您应该通过调整哪个元素指向哪个下一个元素来合并两个列表。

改变你的界面可能更简单:只要有split(struct node **a, struct node **b) 具有前置请求*b = NULL 并将a 的一半节点移动到b;然后merge(struct node **a, struct node **b);b 的所有节点移动到a

【讨论】:

  • 嗨,你能看看我贴的新代码吗
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-09-08
  • 1970-01-01
  • 2021-12-27
  • 2020-05-26
  • 1970-01-01
  • 2014-10-05
  • 2021-06-28
相关资源
最近更新 更多