【问题标题】:How can I sort a Linked List with User inputs?如何使用用户输入对链接列表进行排序?
【发布时间】:2020-01-08 08:06:59
【问题描述】:

我有一个项目,它生成一个链接列表,删除它们并在用户处显示。现在,我想对列表进行排序。 我的结构:

typedef struct YugiohCard {
    char Name[100];
    char CardType[20];
    int Level;
    int Rank;
    int PendulumStage;
    int Link;
    int ATK;
    int DEF;
    char Property[20];
    char MonsterType[40];
    char CardType2[30];
    char Description[500];
    struct YugiohCard* pNext;
    struct YugiohCard* pPrev;
} struYugiohCard;

当用户说:“CardType2 Ascending”时,程序按 CardType2 和 Ascending 对列表进行排序。

在这种情况下,按字母顺序排列。也可以按其他结构内容(Monstertyp、ATK、DEF 等)排序。升序或降序。

如果没有 C++ 的东西,我怎么能做到这一点?

对不起,我的英语不好。我不太擅长这个。

编辑: 这是我的完整代码:

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "time.h"

typedef struct YugiohCard {
    char Name[100];
    char CardType[20];
    int Level;
    int Rank;
    int PendulumStage;
    int Link;
    int ATK;
    int DEF;
    char Property[20];
    char MonsterType[40];
    char CardType2[30];
    char Description[500];
    struct YugiohCard* pNext;
    struct YugiohCard* pPrev;
} struYugiohCard;

bool OutputList(struYugiohCard* pStart)
{
    int count = 0;
    struYugiohCard* current = pStart;  // Initialize current 
    while (current != NULL)
    {
        count++;
        current = current->pNext;
    }

    char answer[265];
    int CountetCardsThatWillBeOutputet;
    printf("How many Yugioh cards would you like to spend? 0 means all, 
            otherwise the number counts. Number of elements in list: %i Input:", 
            count);
    fgets(answer, 265, stdin);
    CountetCardsThatWillBeOutputet = atoi(answer);
    int countOutputetCards = 0;

    if (CountetCardsThatWillBeOutputet > count)
    {
        printf("Please enter a correct number!");
        system("pause");
        return false;
    }
    else if (CountetCardsThatWillBeOutputet == 0)
    {
        CountetCardsThatWillBeOutputet = count;
    }

    system("cls");
    printf("%10s %20s %10s %10s %20s %10s %10s %10s %20s %20s %20s %20s\n", 
    "Name", "CardType", "Level", "Rank", "PendulumStage", "Link", "ATK", 
    "DEF", "Property", "MonsterType", "CardType2", "Description");
    for (struYugiohCard* pOut = pStart; pOut != NULL; pOut = pOut->pNext)
    {
        printf("%10s %20s %10i %10i %20i %10i %10i %10i %20s %20s %20s 
                %20s\n", pOut->Name, pOut->CardType, pOut->Level, pOut- 
                >Rank, pOut->PendelumStage, pOut->Link, pOut->ATK, pOut->DEF, 
                pOut->Property, pOut->MonsterType, pOut->CardType2, pOut- 
                >Description);
        countOutputetCards++;
        if (countOutputetCards == CountetCardsThatWillBeOutputet )
        {
            break;
        }
    }
    system("pause");
}

void DeleteList(struYugiohCard** head_ref)
{
    struct YugiohCard* prev = *head_ref;

    while (*head_ref)
    {
        *head_ref = (*head_ref)->pNext;
        free(prev);
        prev = *head_ref;
    }
}

struYugiohCard* CreateList()
{
    system("cls");
    char answer[265];
    int countedCards;
    printf("\nHow many Yugioh cards would you like to create? Please enter 
            only enter numbers, otherwise you'll crash.");
    fgets(answer, 265, stdin);
    countedCards = atoi(answer);

    struYugiohCard* pFirst = NULL;

    for (int i = 0; i < countedCards; i++)
    {
        struYugiohCard* pNew = 
            (struYugiohCard*)malloc(sizeof(struYugiohCard));
        if (pNew == NULL) break;
        pNew->Name[0] = 'A' + rand() % 26;
        pNew->Name[1] = '\0';
        pNew->CardType[0] = 'A' + rand() % 26;
        pNew->CardType[1] = '\0';
        pNew->Level = 1 + rand() % 12;
        pNew->Rank = 1 + rand() % 13;
        pNew->PendulumStage = 1 + rand() % 12;
        pNew->Link = 1 + rand() % 8;
        pNew->ATK = rand() % 10001;
        pNew->DEF = rand() % 10001;
        pNew->Property[0] = 'A' + rand() % 26;
        pNew->Property[1] = '\0';
        pNew->MonsterType[0] = 'A' + rand() % 26;
        pNew->MonsterType[1] = '\0';
        pNew->CardType2[0] = 'A' + rand() % 26;
        pNew->CardType2[1] = '\0';
        pNew->Description[0] = 'A' + rand() % 26;
        pNew->Description[1] = '\0';
        if (pFirst != NULL)
        {
            pNew->pNext = pFirst;
        }
        else
        {
            pNew->pNext = NULL;
        }
        pFirst = pNew;
    }
    return pFirst;
}

int main()
{   
    struYugiohCard* pStart = NULL;
    printf("\nIMPORTANT: Please maximize the window, otherwise it will not 
            represents everything correctly.");
    do
    {
        system("cls");
        printf("\nDo you want to create a Yugioh card list (YKE) that 
                Delete Yugioh card list(YKL), a single Yugioh card 
                delete(EYKL), sort the list(YKS), the Yugioh- 
                Output card list(YKA) or the program 
                close(Prsc):");
        char answer[265];
        fgets(answer, 265, stdin);
        if (strcmp(answer, "YKE\n") == 0)
        {
            pStart = CreateList();
        }
        else if (strcmp(answer, "YKS\n") == 0)
        {
            //SortList(pStart);
        }
        else if (strcmp(answer, "EYKL\n") == 0)
        {
            //DeleteOneCard(pStart);
        }
        else if (strcmp(answer, "YKL\n") == 0)
        {
            DeleteList(&pStart);
        }
        else if (strcmp(answer, "YKA\n") == 0)
        {
            OutputList(pStart);
        }
        else if (strcmp(answer, "Prsc\n") == 0)
        {
            return 0;
        }
        else
        {
            printf("Please enter a shortcut!");
        }
    } while (true);
}

【问题讨论】:

  • 创建一个指针数组。让数组成员指向列表成员。然后关注this answer。然后,将列表成员按排序顺序串起来。
  • 首先,列表已经存在,但我需要它来排序。我也不明白答案。我是 C 的新手。请举一个带有字符串和整数 ASC 和 DESC 的示例。并解释它是如何工作的。
  • 也许this 有帮助
  • @Jabberwocky,对不起,没有。在您的评论链接中,提问者有一个结构内容,我有 12 个。这对一个有帮助,但对 12 个没有帮助。
  • @a.b_om 结构体有 1 个或 100 个字段都没有关系,您在这里处理的是 指针

标签: c linked-list


【解决方案1】:

制作数组

创建一个指针数组。让数组成员指向列表成员。该代码使用了一个小技巧,以便列表的最后一个元素将其 pNext 成员正确设置为 NULL。

struYugiohCard *arr[size_of_list + 1], **arrp = arr, *iter;

for (iter = list; iter != NULL; iter = iter->pNext) {
    *arrp++ = iter;
}
*arrp = NULL;

写一个比较函数,然后调用qsort

有很多关于如何使用qsort 的示例,但诀窍是编写适当的比较函数。重要的是要意识到qsort 将传入它正在比较的数组元素的地址。由于我们的数组包含指针,所以比较函数将传递指向指针的指针。

在你的情况下,我猜CardType2 Ascending 可能使用strcmp 来实现,它的返回值与qsort 的期望值相匹配(如果a 小于b,则为负数,如果大于b,则为正数比,如果相等则为零):

int cmp_CardType2_Ascending(const void *a, const void *b) {
    const struYugiohCard * const *aa = a;
    const struYugiohCard * const *bb = b;
    return strcmp((*aa)->CardType2, (*bb)->CardType2);
}

//...

qsort(arr, size_of_list, sizeof(*arr), cmp_CardType2_Ascending);

修复你的list

现在,将您的列表重新连接到排序顺序。请注意,最后一次迭代的 pNext 正在使用设置为 NULL 的额外数组成员。

arr[0]->pNext = arr[1];
arr[0]->pPrev = NULL;
for (int i = 1; i < size_of_list; ++i) {
    arr[i]->pNext = arr[i+1];
    arr[i]->pPrev = arr[i-1];
}
list = arr[0];

将其放入函数中

下面是一个将大部分逻辑放入单个函数的函数。排序函数传入,然后这个函数传给qsort

void sort_YugiohCard(struYugiohCard **pList, int size_of_list,
                     int (*By)(const void *, const void *)) {

    if (size_of_list == 0) return;

    struYugiohCard *list = *pList;
    struYugiohCard *arr[size_of_list+1], **arrp = arr, *iter;

    for (iter = list; iter != NULL; iter = iter->pNext)
        *arrp++ = iter;
    *arrp = NULL;

    qsort(arr, size_of_list, sizeof(*arr), By);

    arr[0]->pNext = arr[1];
    arr[0]->pPrev = NULL;
    for (int i = 1; i < size_of_list; ++i) {
        arr[i]->pNext = arr[i+1];
        arr[i]->pPrev = arr[i-1];
    }
    list = arr[0];

    *pList = list;
}

然后,你可以这样调用这个函数:

sort_YugiohCard(&list, 5, cmp_CardType2_Ascending);

列表将按照比较函数确定的排序顺序返回。

演示

Try it online!

【讨论】:

  • 那是 C++ 吗?我认为,那是 C++。我不知道。
  • 它是 C。为您的双向链表更新了答案。
  • 好的。我试试看。
  • 将数据读入结构体数组,使用qsort 对数组进行排序,然后将排序后的结构体添加到列表中将比扫描列表快Orders of Magnitude在每个 insert 上按排序顺序插入节点。答案是正确的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多