繁体   English   中英

如何对链接列表进行冒泡排序?

[英]How do I Bubble Sort a linked list?

我正在尝试创建一个链接列表,并按气泡排序对其进行排序。 我成功创建了链接列表,但是当我尝试对气泡列表进行排序时,会发生一些意外,并且我不知道问题所在。 问题是什么?

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

//the struct of LinkedList
typedef struct Node
{
    int data;
    struct Node * pNext;
}NODE,*PNODE;

PNODE createList();//Creat one LinkedList
int lengthList(PNODE pHead);//get the length of LinkedList
void sortList(PNODE);//bubble sort

int main()
{
    int length;
    PNODE pHead=NULL;
    pHead=createList();
    sortList(pHead);
    return 0;
}
//Create LinkedList
PNODE createList()
{
    int i,n;
    int val;
    PNODE pHead=(PNODE)malloc(sizeof(NODE));
    if(pHead==NULL)
    {
        printf("failed to create!\n");
        exit(-1);
    }
    pHead->pNext=NULL;
    PNODE pTail=pHead;
    printf("please input the length of the LinkedList:");
    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        printf("number %d is:\n",i+1);
        scanf("%d",&val);
        PNODE pNew=(PNODE)malloc(sizeof(NODE));
        if(pNew==NULL)
        {
            printf("failed to create\n");
            exit(-1);
        }
        pNew->data=val;
        pTail->pNext=pNew;
        pNew->pNext=NULL;
        pTail=pNew;
    }
    return pHead;
}
//get the length of LinkedList
int lengthList(PNODE pHead)
{
    int i=0;
    PNODE p=pHead->pNext;
    while(p!=NULL)
{
        i++;
        p=p->pNext;
    }
    return i;
}
//bubble sort
void sortList(PNODE pHead)
{
    int i,j,t,len;
    PNODE p,q;
    len=lengthList(pHead);
    p=pHead->pNext;
    for(i=0;i<len-1;i++)
    {
        for(j=0;j<len-i;j++)
        {
            q=p->pNext;
            if( p->data > q->data)
            {
                t=p->data;
                p->data=q->data;
                q->data=t;
            }
            p=q;//here may be the error
        }
    }
    return;
}

您正在sortList中的列表末尾运行

p=pHead->pNext;
for(i=0;i<len-1;i++)
{
    for(j=0;j<len-i;j++)
    {
        q=p->pNext;
        ....
        p=q;//here may be the error
    }
}

错误1)您的列表只有len长,但您正尝试将p推进到p->pNext远超过len倍。

错误2)pHead不必是完整的NODE-它只是PNODE指针。 您永远不会使用其数据字段。 您应该让pHead指向列表中的第一个节点,然后从pHead而不是pHead-> pNext开始迭代。

错误3)您永远不会清理内存分配。

正如@Airsource指出的错误,请记住,大多数错误是由于程序的设计选择不当造成的。 尝试像下面那样做,您将遇到更少的错误

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

typedef struct _Node{
    int data;
    struct _Node* next;
}Node;

typedef struct {
    Node* headPtr;
    Node* tailPtr;
    unsigned size;
}List;

static void create_node(List* list, int element) {
    if (list->headPtr == NULL) {
        // List is empty
        list->headPtr = (Node* )malloc(sizeof(Node));
        list->headPtr->data = element;
        list->headPtr->next = 0;
        list->tailPtr = list->headPtr;
        list->size++;
    }else{
        // List was already populated
        Node* temp = (Node* )malloc(sizeof(Node));
        temp->data = element;
        temp->next = 0;
        list->tailPtr->next = temp;
        list->tailPtr = temp;
        list->size++;
    }
}

void create_list(List* list, int length){
    int ele;
    int i;
    list->headPtr = list->tailPtr = 0;
    list->size = 0;

    for (i = 0; i < length; i++) {
        scanf("%d", &ele);
        create_node(list, ele);
    }
}

void print_list(List* list){
    Node* loop = list->headPtr;
    while(loop){
        printf("%d ", loop->data);
        loop = loop->next;
    }
    printf("\n");
}


 int main(){
    List* list;
    int n;
    printf("Enter the length of the list: ");
    scanf("%d", &n);
    create_list(list, n);
    print_list(list);
    bubble_sort(list);
    print_list(list);
    if (cleanup(list))
        printf("Memory rescued!!\n");
    else
        printf("OOPS!! Error\n");
 return 0;
}

而且,您可以随时通过list->size 无需单独的功能即可执行此操作。

最后,使用气泡排序对其进行排序,您可以在下面执行以下操作

void bubble_sort(List* list) {
    int i, j;
    Node* first, *second;
    int temp;
    first = list->headPtr;
    second = list->headPtr->next;
    for (i = 0; i < list->size - 1; i++) {
        for (j = 0; j < list->size - i - 1; j++) {
            if (first->data > second->data){
                temp = first->data;
                first->data = second->data;
                second->data = temp;
            }
            first = second;
            second = second->next;
        }
        first = list->headPtr;
        second = list->headPtr->next;
    }
}

为了清理,您可以这样做

bool cleanup(List* list) {
    Node* curr = list->headPtr;
    Node* nxt = list->headPtr->next;
    while(nxt){
        free(curr);
        curr = nxt;
        nxt = curr->next;
    }
    list->headPtr = list->tailPtr = 0;
    list->size = 0;
    return !nxt ? true: false;
}

您的程序中有几个错误。 我将一一解答:

  1. 第28行PNODE pHead=(PNODE)malloc(sizeof(NODE)); 在这里,在检查n是否大于0之前,您正在分配内存并创建节点。

  2. 第36行printf("please input the length of the LinkedList:");
    至此,您已经创建了一个节点,其中的head节点没有任何值(因此包含垃圾)

实际上,您的createList()创建的链表具有n+1节点而不是n ,并且head->value包含垃圾。

解:

printf("please input the length of the LinkedList:");
scanf("%d", &n);
for(i=0; i<n; i++)
{
    PNODE pNew = (PNODE)malloc(sizeof(NODE));

    if(pNew == NULL)
    {
        printf("failed to create!\n");
        exit(-1);
    }

    scanf("%d", &val);
    pNew->data = val;
    pNew->pNext = NULL;

    if (!i)
        pHead = pNew;
    else
        pTail->pNext = pNew;
    pTail = pNew;      
}

return pHead;
  1. 第59行PNODE p=pHead->pNext;
    在这里,您正在计算从第二个节点开始的节点(不包括head )。 难怪你会得到lengthn为您创建长度的链表n+1createList()

想象一下,如果n = 0从而pHead = NULL怎么办?
然后此行将导致SegFault

解:
更改PNODE p=pHead->pNext; PNODE p = pHead;

  1. 第73行p=pHead->pNext;
    在这里,您将开始排序,排除第一个节点( head节点)。
    也这应该是outter内for和外部内的for给复位p为每个通第一个节点。

  2. 第76行for(j=0;j<len-i;j++)
    这里j必须小于len - 1 - i如在传递1( i = 0 )时,在最坏的情况下j等于len-1 j < len-i ,其中p指向链表的最后一个节点当q = p -> pNextq将为NULL。 这将使q->data产生SegFault

总而言之,您的排序例程在第一次通过时就产生了SegFault ,即使它没有(通过适当地调整内部for的循环终止表达式),外部for循环也没有对排序做出任何贡献,只是增加了时间复杂度。

解:

for(i = 0; i < len - 1; i++)
{
    p = pHead;
    for(j = 0; j < len - 1 - i; j++)
    {
        q = p -> pNext;
        if(p->data > q->data)
        {
            t = p -> data;
            p -> data = q -> data;
            q -> data = t;
        }
        p = q;
    }
}

一个问题:
您如何检查元素是否已排序?
printList()例程将有助于发现上述错误。

“始终通过在处理输入之前显式打印输入来验证您是否正确存储了输入!”

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM