2012-08-05 106 views
5

我试图通过查找最大值,从其位置删除它,然后将其插入列表顶部来对链表进行排序。在C中排序链接列表

我遇到的困难是实际删除并插入顶部。这个问题似乎是在sortList函数中包含的while循环中的if条件中,但我不知道如何解决它。

任何帮助,将不胜感激。

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

typedef struct node{ 
    int num; 
    struct node *next; 
} Node, *NodePtr; 

void printList(NodePtr np); 
NodePtr makeList(void); 
NodePtr makeNode(int n); 
NodePtr sortList(NodePtr list); 

int main(void) { 
    NodePtr list; 
    printf("Enter numbers for the list (0 to end)\n"); 
    list = makeList(); 
    printList(list); 
    list = sortList(list); 
    printList(list); 
    return 0; 
} 

NodePtr makeList(void) { 
    NodePtr makeNode(int), np, top, last; 
    int n; 
    top = NULL; 
    if(scanf("%d", &n) != 1)n = 0; 
    while(n != 0) { 
     np = makeNode(n); 
     if(top == NULL)top = np; 
     else last->next = np; 
     last = np; 
     if(scanf("%d", &n)!=1)n=0; 
    } 
    return top; 
} 


void printList(NodePtr np) { 
    while(np != NULL) { 
     printf("%d\n", np->num); 
     np = np->next; 
    } 
} 

NodePtr makeNode(int n) { 
    NodePtr np = (NodePtr)malloc(sizeof(Node)); 
    np->num = n; 
    np->next = NULL; 
    return np; 
} 

NodePtr sortList(NodePtr list) { 
    NodePtr top = list; 
    NodePtr curr = NULL; 
    NodePtr largest; 
    NodePtr prev; 
    prev = NULL; 
    curr = top; 
    largest = top; 

    while(curr != NULL) { 
     prev = curr; 
     if(curr->num > largest->num) { 
      largest = curr; 
      prev->next = curr->next; 
      largest->next = top; 
     } 
     curr = curr->next; 
    } 
    if(prev == NULL) { 
     largest->next = top; 
     return largest; 
    } 
    return largest; 
} 
+2

有许多关于用C排序链表的问题;其中很多被列为页面RHS的相关问题。你看过他们中的任何一个,看他们是否与你的问题有关? – 2012-08-05 03:24:48

回答

0

This应该真的能帮到你。这是一个非常好的帖子。

+0

堆栈溢出的答案应该通常自己(虽然引用是伟大的)。如果您想分享链接,可以在评论中这样做。 – 2012-08-05 03:44:07

+0

经验教训。会做。 – Prasanth 2012-08-05 03:46:46

0

通过写信给largest->next您覆盖curr->next。所以你最终总是从顶端重新开始。

确保:

  1. 名单保持一致
  2. 您的列表迭代器保持一致

但总体而言,你的代码似乎被严重打破,我认为有可能是一对夫妇排序逻辑中的其他错误。

0

下面是一些存在于你的排序逻辑的问题:

  1. 您设置分组指针CURR在循环本身这是不正确的开始。通过这样做,您将使当前指针和前一个节点指针相同,从而无法删除该节点。
  2. 您应该将最大的指针也分配给顶端,从而有助于设置真正的顶级节点的最大 - >旁边的可能性。

的代码可以修改象下面这样(只是一个指针,你需要检查的其他问题你自己):

while(curr != NULL) 
{ 

    if(curr->num > largest->num) 
    { 
     largest = curr; 
     prev->next = curr->next; 
     largest->next = top; 
     top = largest; 

    } 
    prev = curr; 
    curr = curr->next; 
} 
+0

还有一个指针问题,curr将始终处于顶端:较大的指向与curr相同的节点。你把top-> next放在顶部,然后curr-> next放到顶部。当你写curr = curr-> next时,你实际上把curr放在最前面(因为你已经写了最大的(最大的= curr))。所以你从顶端回避无限。 – 2012-08-05 10:33:37

1

有一个在sortList功能的问题。

该功能只将一些大型节点放在列表的开头。这不是全部列表。你可以通过排序算法对文件进行排序:quicksort/bubblesort/... 我在这个答案的最后给出了一个排序的代码。

这里是干什么的排序列表的代码:

//它与第一个替换最大的节点,然后做与子表相同的操作(列表第一个元素)

NodePtr sortList(NodePtr list) 
{ 

// 
if(list == null || list->next == null) 
    return list; // the list is sorted. 

//replace largest node with the first : 

//1- find largest node : 
NodePtr curr, largest,largestPrev; 
curr = list; 
largest = list; 
prev = list; 
largestPrev = list; 
while(curr != NULL) { 
     if(curr->num > largest->num) { 
      largestPrev = prev; 
      largest = curr; 
     } 
     prev = curr; 
     curr = curr->next; 

    } 
//largest node is in largest. 

//2- switching firt node and largest node : 
NodePtr tmp; 
if(largest != list) 
{ 
    largestPrev->next = list; 
    tmp = list->next; 
    list->next = largest->next; 
    largest->next = tmp; 
} 

// now largest is the first node of the list. 

// calling the function again with the sub list : 
//   list minus its first node : 
largest->next = sortList(largest->next); 


return largest; 
} 
+1

请更正您的代码(prev始终指向您答案中的尾部),您必须添加新指针largest_prev,并在if:(curr-> num> largest-> num)的情况下将其设置为prev,然后使用它而不是prev(largest_prev-> next = list) – TOC 2012-08-05 14:52:50

+0

@TOC:ty,完成。更可识别的代码将是使用搜索最大元素和切换节点的函数的函数。 – 2012-08-06 06:54:43

+0

当你有这样的列表时,这个算法不起作用:524361 – user1511417 2015-02-03 20:12:07

1

这里是我尝试使用QuickSort算法对单个链表进行排序。如果你知道n,那么运行时间将是O(n log n)。检查这是否有帮助。

#include "malloc.h" 

typedef struct node { 
    struct node *next; 
    int val; 
} node; 

bool insert_node(struct node **head, int val) 
{ 
    struct node *elem; 
    elem = (struct node *)malloc(sizeof(struct node)); 
    if (!elem) 
     return false; 
    elem->val = val; 
    elem->next = *head; 
    *head = elem; 
    return true; 
} 

int get_lval(struct node *head, int l) 
{ 
    while(head && l) { 
     head = head->next; 
     l--; 
    } 
    if (head != NULL) 
     return head->val; 
    else 
     return -1; 
} 

void swap(struct node *head, int i, int j) 
{ 
    struct node *tmp = head; 
    int tmpival; 
    int tmpjval; 
    int ti = i; 
    while(tmp && i) { 
     i--; 
     tmp = tmp->next; 
    } 
    tmpival = tmp->val; 
    tmp = head; 
    while(tmp && j) { 
     j--; 
     tmp = tmp->next; 
    } 
    tmpjval = tmp->val; 
    tmp->val = tmpival; 
    tmp = head; 
    i = ti; 
    while(tmp && i) { 
     i--; 
     tmp = tmp->next; 
    } 
    tmp->val = tmpjval; 
} 


struct node *Quick_Sort_List(struct node *head, int l, int r) 
{ 
    int i, j; 
    int jval; 
    int pivot; 
    i = l + 1; 
    if (l + 1 < r) { 
     pivot = get_lval(head, l); 
     printf("Pivot = %d\n", pivot); 
     for (j = l + 1; j <= r; j++) { 
      jval = get_lval(head, j); 
      if (jval < pivot && jval != -1) { 
       swap(head, i, j); 
       i++; 
      } 
     } 
     swap(head, i - 1, l); 
     Quick_Sort_List(head, l, i); 
     Quick_Sort_List(head, i, r); 
    } 
    return head; 
} 

struct node *Sort_linkedlist(struct node *head) 
{ 
    struct node *tmp = head; 
    // Using Quick sort. 
    int n = 0; 

    while (tmp) { 
     n++; 
     tmp = tmp->next; 
    } 
    printf("n = %d\n", n); 
    head = Quick_Sort_List(head, 0, n); 
    return head; 
} 

void print_list(struct node *head) 
{ 
    while(head) { 
     printf("%d->", head->val); 
     head = head->next; 
    } 
    printf("\n"); 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    struct node *head = NULL; 
    struct node *shead = NULL; 

    insert_node(&head, 10); 
    insert_node(&head, 12); 
    insert_node(&head, 9); 
    insert_node(&head, 11); 
    insert_node(&head, 7); 
    insert_node(&head, 1); 
    insert_node(&head, 3); 
    insert_node(&head, 8); 
    insert_node(&head, 5); 
    insert_node(&head, 2); 
    insert_node(&head, 4); 
    insert_node(&head, 6); 
    print_list(head); 

    shead = Sort_linkedlist(head); 
    print_list(shead); 

    return 0; 
} 
0
// Program to sort a single linked list in ascending order 
// (without exchanging data in the nodes) 
/************************************************************************** 

There are two methods of sorting presented here(At a time,we can use any of 
these two functions to sort our single linked list.) - 

1. Function 'void Sort()' - This function uses selection sort method(I 
          think). 
    In this function,a node whose data is the smallest in the list is made 
    as 'head' node(i.e. starting node of the list) by scanning the whole list 
    once.Then from the remaining list,again a node with the smallest data is 
    found out whose address is kept in the 'next' field of previous node(head 
    node).This process continues to sort the whole list. 
2. Function 'void Sort_method2()' - This function uses insertion sort 
            method(I think). 
    In this function,starting from second node in the list, all previous node 
    data(starting from 'head' node) are compared with current reference node 
    (which is initially second node in the list).If 'data' field of current 
    reference node is smaller than that of any of its previous nodes,then 
    suitable changes in the 'next' field of corresponding nodes are made.If 
    data in the current reference node is smaller than that in the 'head' node, 
    then the current reference node is made as 'head' node. 

    *********************************************************************/ 

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

struct node 
{ 
int data; 
struct node *next; 
}; 

struct node *head,*head1; 

void Create_node(int data); 
void display(); 
void Sort(); 
void Sort_method2(); 


void main() 
{ 
int choice,d; 
clrscr(); 
while(1) 
{ 
    printf("\n 1.Create new node"); 
    printf("\n 2.Sort in ascending order"); 
    printf("\n 3.Exit"); 
    printf("\nEnter your choice : "); 
    scanf("%d",&choice); 

    switch(choice) 
    { 
    case 1: printf("\nEnter data :"); 
      scanf("%d",&d); 
      Create_node(d); 
      break; 
    case 2: Sort();  // At a time,we can use any of these two 
      //Sort_method2(); // functions to sort our single linked list. 
      break; 
    case 3: exit(0); 
    default:exit(0); 
    } 
    } // end of while(1) 
} // end of main() 

//-------------------------------------------- 
void Create_node(int d) 
{ 
    struct node *newnode,*temp; 
    newnode = (struct node *)malloc(sizeof(struct node)); 
    newnode -> data = d; 
    newnode -> next = NULL; 
    if(head == NULL) 
    head = newnode; 
    else 
    { 
     temp = head; 
     while(temp -> next != NULL) 
     temp = temp -> next; 

     temp -> next = newnode; 
    } // end of 'else' 
} // end of 'Create_node(int d)' 

//--------------------------------------------- 
void display() // Print linked list contents 
{ 
    struct node *temp; 
    printf("\nList contents are :\n"); 
    temp = head; 
    while(temp != NULL) 
    { 
    printf(" Data = %d Address = %u\n",temp->data,temp); 
    temp = temp->next; 
    } 
    printf("\n"); 
} 
//-------------------------------------------- 
void Sort() 
{ 
    struct node *t,*t1,*t2,*t3; 
    t1 = head; 
    head1 = head; 
    if(head == NULL) 
    printf("\nThe linked list is empty!"); 
    else 
    { 
    while((t2 = t1 -> next) != NULL) 
    { 
     while(t2 != NULL) 
     { 
     t3 = t2 -> next; 
     if(t1 -> data > t2 -> data) 
     { 
      t2 -> next = t1; 
      for(t = t1; t -> next != t2;t = t -> next); 

      t -> next = t3; 
      t1 = t2;  // t1 = Node with smaller data 
      t2 = t3;  // t2 = Node to be compared with t1 
     } // end of 'if' 
     else 
     { 
      // t1 = t1;  // That is,no change in t1. 
      t2 = t3; 
     } 
     } // end of ' while(t2 != NULL)' 

     if(head == head1) // We want this action only for first pass of 
     {     // outer while() loop.Only initially, head = head1. 
     head = t1; 
     head1 = t1 -> next; 
     } // end of 'if(head == head1)' 
     else 
     { 
     for(t = head;t -> next != head1; t = t -> next); 

     t -> next = t1; 
     head1 = t1 -> next; 
     } // end of 'else' 

     t1 = t1 -> next; 
    } // end of 'while((t2 = t1 -> next) != NULL)' 

    display(); // Display the list. 
    } // end of 'else' of 'if(head == NULL)' 
} // end of 'Sort()' 

//-------------------------------------------- 
void Sort_method2() 
{ 
struct node *t,*t1,*t2,*tt; 
if(head == NULL) 
    printf("\nThe linked list is empty!"); 
else 
{ 
    t1 = head -> next; 
    while(t1 != NULL)       // This is i-loop(outer loop). 
    { 
    t2 = t1 -> next; 
    for(t = head; t != t1; t = t -> next) // This is j-loop(inner loop). 
    { 
     if(t1->data < t->data) 
     { 
     t1 -> next = t; 
     for(tt=head; tt->next != t1; tt=tt->next); //end of for loop in 'if' 

     tt -> next = t2; 
     if(t == head) 
      head = t1; // There is only one statement in this 'if'. 
     else // i.e.,'if(t != head)' 
     { 
      for(tt=head; tt->next != t; tt=tt->next); 

      tt -> next = t1; 
     } 
     break; 
     } // end of 'if' 
    } // end of outer 'for' loop 
    t1 = t2; 
    }  // end of 'while' 

    display(); // Display the list. 
}  // end of 'else' of 'if(head == NULL)' 
}   // end of 'Sort_method2()'