链接列表 - C中的堆栈排序

发布于 2025-01-21 13:05:17 字数 6605 浏览 2 评论 0原文

我的代码如下:

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

struct stack {
    int data;
    struct stack* next;
};
struct Student
{
    unsigned long int rollnumber;
    char name[100];
    struct Student *next;
    
}* head;
// Utility function to initialize stack
void initStack(struct stack** s) { *s = NULL; }
 
// Utility function to check if stack is empty
int isEmpty(struct stack* s)
{
    if (s == NULL)
        return 1;
    return 0;
}
 
// Utility function to push an item to stack
void push(struct stack** s, int x, unsigned long int rollnumber, char *name)
{
    struct stack* p = (struct stack*)malloc(sizeof(*p));
 
    if (p == NULL) {
        fprintf(stderr, "Memory allocation failed.\n");
        return;
    }
 
    p->data = x;
    p->next = *s;
    *s = p;
}
 
// Utility function to remove an item from stack
int pop(struct stack** s)
{
    int x;
    struct stack* temp;
 
    x = (*s)->data;
    temp = *s;
    (*s) = (*s)->next;
    free(temp);
 
    return x;
}

// Function to find top item
int top(struct stack* s) { return (s->data); }

// Recursive function to insert an item x in sorted way
void sortedInsert(struct stack** s, int x, unsigned long int rollnumber, char *name)
{
    // Base case: Either stack is empty or newly inserted
    // item is less than top (more than all existing)
    if (isEmpty(*s) || x < top(*s)) {
        push(s, x, rollnumber, name);
        return;
    }
    else{
    // If top is less, remove the top item and recur
    int temp = pop(s);
    sortedInsert(s, x, rollnumber, name);
 
    // Put back the top item removed earlier
    push(s, temp, rollnumber, name);}
}
 
// Function to sort stack
void sortStack(struct stack** s)
{
    // If stack is not empty
    char *name;
    unsigned long int rollnumber;
    if (!isEmpty(*s)) {
        // Remove the top item
        int x = pop(s);
 
        // Sort remaining stack
        sortStack(s);
 
        // Push the top item back in sorted stack
        sortedInsert(s, x, rollnumber, name);
    }
}
// Utility function to print contents of stack
void printStack(struct stack* s, unsigned long int rollnumber, char* name)
{
    struct Student* student = (struct Student *) malloc(sizeof(struct Student));
    struct Student* temp = head;
    while (s && temp!=NULL) {
        printf("%lu %s\n", temp->rollnumber, temp->name);
        s = s->next;
        temp = temp->next;
    }

    printf("\n");
}

void insert(unsigned long int rollnumber, char* name)
{
    
    struct Student * student = (struct Student *) malloc(sizeof(struct Student));
    student->rollnumber = rollnumber;
    strcpy(student->name, name);
    student->next = NULL;
    
    if(head==NULL){
        // if head is NULL
        // set student as the new head
        head = student;
    }
    else{
        // if list is not empty
        // insert student in beginning of head
        student->next = head;
        head = student;
    }
    
}

void Delete(unsigned long int rollnumber)
{
    struct Student * temp1 = head;
    struct Student * temp2 = head; 
    while(temp1!=NULL){
        
        if(temp1->rollnumber==rollnumber){
            
            printf("Record with roll number %lu Found\n", rollnumber);
            
            if(temp1==temp2){
                // this condition will run if
                // the record that we need to delete is the first node
                // of the linked list
                head = head->next;
                free(temp1);
            }
            else{
                // temp1 is the node we need to delete
                // temp2 is the node previous to temp1
                temp2->next = temp1->next;
                free(temp1); 
            }
            
            printf("Record successfully deleted\n");
            return;
            
        }
        temp2 = temp1;
        temp1 = temp1->next;
        
    }
printf("Student with roll number %lu is not found\n", rollnumber);
    
}
void display()
{
    struct Student * temp = head;
    while(temp!=NULL){
        
        printf("Roll Number: %lu\n", temp->rollnumber);
        printf("Name: %s\n", temp->name);
        temp = temp->next;
        
    }
}

int main(void)
{
    head = NULL;
    int choice;
    int fc_,id_,year_, fc_year;
    char name[100];
    struct student* s;
    unsigned long int rollnumber;
    struct stack* faculty;
    struct stack* year;
    struct stack* id;
    initStack(&faculty);
    initStack(&year);
    initStack(&id);
    printf("1 - Enter school number\n2 - Display school numbers by ID\n3 - Display school numbers sorted by year\n4 - Display school numbers sorted by the faculty codes\n5 - Delete a record by school number\n6 - Exit");
    do
    {
        printf("\nEnter Choice: ");
        scanf("%d", &choice);
        switch (choice)
        {
            case 1:
                printf("Enter roll number: ");
                scanf("%lu", &rollnumber);
                fc_ = rollnumber/pow(10, 6);
                id_ = rollnumber%(10*10*10*10);
                fc_year = rollnumber/pow(10,4);
                year_ = fc_year%(100);
                printf("Enter name: ");
                scanf("%s", name);
                insert(rollnumber, name);
                push(&faculty, fc_, rollnumber, name);
                push(&year, year_, rollnumber, name);
                push(&id, id_, rollnumber, name);
                break;
            case 2:
                printf("Sorted by ID: \n");
                sortStack(&id);
                printStack(id, rollnumber, name);
                break;
            case 3:
                printf("Sorted by year: \n");
                sortStack(&year);
                printStack(year, rollnumber, name);
                break;
            case 4:
                printf("Sorted by faculty code: \n");
                sortStack(&faculty);
                printStack(faculty, rollnumber, name);
                break;
            case 5:
                printf("Enter roll number to delete: ");
                scanf("%lu", &rollnumber);
                Delete(rollnumber);
                break;
            case 6:
                break;
        }
        
    } while (choice != 6);
}

例如,当选择是2时,我想以升序显示学生名称和整个滚动名称。但是,当我运行它是我得到的(c,b,a是我给出的名称):

Enter Choice: 2
705102020 C
705102010 B
705102005 A

我确定我对其进行了正确的排序,但是可能我的printStack函数无法正常工作。我该如何扭转这一点?

My code is following:

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

struct stack {
    int data;
    struct stack* next;
};
struct Student
{
    unsigned long int rollnumber;
    char name[100];
    struct Student *next;
    
}* head;
// Utility function to initialize stack
void initStack(struct stack** s) { *s = NULL; }
 
// Utility function to check if stack is empty
int isEmpty(struct stack* s)
{
    if (s == NULL)
        return 1;
    return 0;
}
 
// Utility function to push an item to stack
void push(struct stack** s, int x, unsigned long int rollnumber, char *name)
{
    struct stack* p = (struct stack*)malloc(sizeof(*p));
 
    if (p == NULL) {
        fprintf(stderr, "Memory allocation failed.\n");
        return;
    }
 
    p->data = x;
    p->next = *s;
    *s = p;
}
 
// Utility function to remove an item from stack
int pop(struct stack** s)
{
    int x;
    struct stack* temp;
 
    x = (*s)->data;
    temp = *s;
    (*s) = (*s)->next;
    free(temp);
 
    return x;
}

// Function to find top item
int top(struct stack* s) { return (s->data); }

// Recursive function to insert an item x in sorted way
void sortedInsert(struct stack** s, int x, unsigned long int rollnumber, char *name)
{
    // Base case: Either stack is empty or newly inserted
    // item is less than top (more than all existing)
    if (isEmpty(*s) || x < top(*s)) {
        push(s, x, rollnumber, name);
        return;
    }
    else{
    // If top is less, remove the top item and recur
    int temp = pop(s);
    sortedInsert(s, x, rollnumber, name);
 
    // Put back the top item removed earlier
    push(s, temp, rollnumber, name);}
}
 
// Function to sort stack
void sortStack(struct stack** s)
{
    // If stack is not empty
    char *name;
    unsigned long int rollnumber;
    if (!isEmpty(*s)) {
        // Remove the top item
        int x = pop(s);
 
        // Sort remaining stack
        sortStack(s);
 
        // Push the top item back in sorted stack
        sortedInsert(s, x, rollnumber, name);
    }
}
// Utility function to print contents of stack
void printStack(struct stack* s, unsigned long int rollnumber, char* name)
{
    struct Student* student = (struct Student *) malloc(sizeof(struct Student));
    struct Student* temp = head;
    while (s && temp!=NULL) {
        printf("%lu %s\n", temp->rollnumber, temp->name);
        s = s->next;
        temp = temp->next;
    }

    printf("\n");
}

void insert(unsigned long int rollnumber, char* name)
{
    
    struct Student * student = (struct Student *) malloc(sizeof(struct Student));
    student->rollnumber = rollnumber;
    strcpy(student->name, name);
    student->next = NULL;
    
    if(head==NULL){
        // if head is NULL
        // set student as the new head
        head = student;
    }
    else{
        // if list is not empty
        // insert student in beginning of head
        student->next = head;
        head = student;
    }
    
}

void Delete(unsigned long int rollnumber)
{
    struct Student * temp1 = head;
    struct Student * temp2 = head; 
    while(temp1!=NULL){
        
        if(temp1->rollnumber==rollnumber){
            
            printf("Record with roll number %lu Found\n", rollnumber);
            
            if(temp1==temp2){
                // this condition will run if
                // the record that we need to delete is the first node
                // of the linked list
                head = head->next;
                free(temp1);
            }
            else{
                // temp1 is the node we need to delete
                // temp2 is the node previous to temp1
                temp2->next = temp1->next;
                free(temp1); 
            }
            
            printf("Record successfully deleted\n");
            return;
            
        }
        temp2 = temp1;
        temp1 = temp1->next;
        
    }
printf("Student with roll number %lu is not found\n", rollnumber);
    
}
void display()
{
    struct Student * temp = head;
    while(temp!=NULL){
        
        printf("Roll Number: %lu\n", temp->rollnumber);
        printf("Name: %s\n", temp->name);
        temp = temp->next;
        
    }
}

int main(void)
{
    head = NULL;
    int choice;
    int fc_,id_,year_, fc_year;
    char name[100];
    struct student* s;
    unsigned long int rollnumber;
    struct stack* faculty;
    struct stack* year;
    struct stack* id;
    initStack(&faculty);
    initStack(&year);
    initStack(&id);
    printf("1 - Enter school number\n2 - Display school numbers by ID\n3 - Display school numbers sorted by year\n4 - Display school numbers sorted by the faculty codes\n5 - Delete a record by school number\n6 - Exit");
    do
    {
        printf("\nEnter Choice: ");
        scanf("%d", &choice);
        switch (choice)
        {
            case 1:
                printf("Enter roll number: ");
                scanf("%lu", &rollnumber);
                fc_ = rollnumber/pow(10, 6);
                id_ = rollnumber%(10*10*10*10);
                fc_year = rollnumber/pow(10,4);
                year_ = fc_year%(100);
                printf("Enter name: ");
                scanf("%s", name);
                insert(rollnumber, name);
                push(&faculty, fc_, rollnumber, name);
                push(&year, year_, rollnumber, name);
                push(&id, id_, rollnumber, name);
                break;
            case 2:
                printf("Sorted by ID: \n");
                sortStack(&id);
                printStack(id, rollnumber, name);
                break;
            case 3:
                printf("Sorted by year: \n");
                sortStack(&year);
                printStack(year, rollnumber, name);
                break;
            case 4:
                printf("Sorted by faculty code: \n");
                sortStack(&faculty);
                printStack(faculty, rollnumber, name);
                break;
            case 5:
                printf("Enter roll number to delete: ");
                scanf("%lu", &rollnumber);
                Delete(rollnumber);
                break;
            case 6:
                break;
        }
        
    } while (choice != 6);
}

When, for example, the choice is 2, I want to display the student name and whole rollnumber in ascending order. But when I run it that is what I get (C, B, A are the names given by me):

Enter Choice: 2
705102020 C
705102010 B
705102005 A

I am sure that I sorted it correctly, but probably my printStack function is not working properly. How can I reverse this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

寻找一个思念的角度 2025-01-28 13:05:17

最好独立于代码的其余部分定义堆栈结构:

struct stack {
    void *data;
    struct stack *next;
};

void stack_init(struct stack **ss)
{
    *ss = NULL;
}

bool stack_push(struct stack **ss, void *data)
{
    struct stack *node = malloc(sizeof *node);
    if (!node) return false;
    
    node->data = data; // Copy address, not data
    node->next = *ss;
    *ss = node;
    
    return true;
}

bool stack_pop(struct stack **ss, void **data)
{
    if (!*ss) return false;
    
    struct stack *rm = *ss;
    *ss = (*ss)->next;
    if (data) *data = rm->data; // If nothing is provided (i.e. NULL), data will leak if it was allocated dynamically.
    free(rm);
    
    return true;
}

bool stack_top(const struct stack *ss, void **data)
{
    if (!ss) return false;
    
    *data = ss->data;
    return true;
}

void stack_print(const struct stack *ss, void print(const struct stack*))
{
    for (const struct stack *sp = ss; sp; sp = sp->next)
        print(sp);
}

您可以像这样实现堆栈排序函数:

struct stack *stack_find_min(struct stack *ss, int (*cmp)(const void*, const void*))
{
    struct stack *min = ss;
    for (struct stack *sp = ss; sp; sp = sp->next)
        if (cmp(sp->data, min->data) < 0)
            min = sp;
    
    return min;
}

void stack_sort(struct stack *ss, int (*cmp)(const void*, const void*))
{
    if (!ss) return;
    
    for (struct stack *sp = ss; sp; sp = sp->next) {
        struct stack *min = stack_find_min(sp, cmp);
        swap(&sp->data, &min->data);
    }
}

swap()交换两个指针:

void swap(void **p1, void **p2)
{
    void *tmp = *p1;
    *p1 = *p2;
    *p2 = tmp;
}

此后,定义您的学生数据结构:

struct student {
    unsigned long rollnumber;
    char name[100];
    struct student *next;
};

struct student *student_insert(struct student **head, unsigned long rollnumber, const char *name)
{
    struct student *st = malloc(sizeof(*st));
    if (!st) return NULL;
    
    st->rollnumber = rollnumber;
    strncpy(st->name, name, 99);
    st->next = *head;
    *head = st;
    
    return st;
}

void student_print(const struct stack *ss)
{
    struct student *st = ss->data;
    printf("%ld\t%s\n", st->rollnumber, st->name);
}

int student_compare_id(const void *s1, const void *s2)
{
    // MUST cast void* into (struct student*) first.
    const struct student *student1 = s1;
    const struct student *student2 = s2;
    
    unsigned long rollnumber1 = student1->rollnumber;
    unsigned long rollnumber2 = student2->rollnumber;
    
    unsigned long id1 = rollnumber1 % 10000;
    unsigned long id2 = rollnumber2 % 10000;
    
    return id1 == id2 ? 0 : (id1 < id2 ? -1 : 1);
}

如果要测试上述:

int main(void)
{
    struct stack *ss;
    stack_init(&ss);

    struct student *st = NULL;
    student_insert(&st, 100181234, "James");
    student_insert(&st, 200195678, "John");
    student_insert(&st, 300200324, "Goku");
    student_insert(&st, 400214321, "Taylor");
    
    for (struct student *p = st; p; p = p->next)
        stack_push(&ss, p);

    puts("Unsorted stack:");    
    stack_print(ss, student_print);
    
    stack_sort(ss, student_compare_id);
    
    puts("\nSorted by ID:");
    stack_print(ss, student_print);

    // Don't forget to free the memory allocated for students
    // and pop all nodes of the stack (ommited here).
}

输出:

Unsorted stack:
100181234   James
200195678   John
300200324   Goku
400214321   Taylor

Sorted by ID:
300200324   Goku
100181234   James
400214321   Taylor
200195678   John

更多的事情:

  • 不要使用scanf()读取用户输入。 fgets() 更安全。
  • 您可以直接替换pow(10,4) 10000。为什么浪费CPU周期来计算常数?
  • 在您的insert()函数中,无需测试*head == null。其他语句中的代码处理这种情况。

编辑:student_compare_id()中,const void*必须将指针施加到const> const struct Struct Student*首先提出。以前的版本似乎工作是因为滚动词恰好是结构中的第一个字段。这是其所有荣耀的不确定行为。现在修复了。

这是没有人应该使用的先前版本:

int student_compare_id(const void *s1, const void *s2)
{
    unsigned long rollnumber1 = *(unsigned long*)s1; // WRONG!
    unsigned long rollnumber2 = *(unsigned long*)s2; // WRONG!
    
    unsigned long id1 = rollnumber1 % 10000;
    unsigned long id2 = rollnumber2 % 10000;
    
    return id1 == id2 ? 0 : (id1 < id2 ? -1 : 1);
}

It would be better to define a stack struct independantly of the rest of your code:

struct stack {
    void *data;
    struct stack *next;
};

void stack_init(struct stack **ss)
{
    *ss = NULL;
}

bool stack_push(struct stack **ss, void *data)
{
    struct stack *node = malloc(sizeof *node);
    if (!node) return false;
    
    node->data = data; // Copy address, not data
    node->next = *ss;
    *ss = node;
    
    return true;
}

bool stack_pop(struct stack **ss, void **data)
{
    if (!*ss) return false;
    
    struct stack *rm = *ss;
    *ss = (*ss)->next;
    if (data) *data = rm->data; // If nothing is provided (i.e. NULL), data will leak if it was allocated dynamically.
    free(rm);
    
    return true;
}

bool stack_top(const struct stack *ss, void **data)
{
    if (!ss) return false;
    
    *data = ss->data;
    return true;
}

void stack_print(const struct stack *ss, void print(const struct stack*))
{
    for (const struct stack *sp = ss; sp; sp = sp->next)
        print(sp);
}

You can implement your stack sorting function like that:

struct stack *stack_find_min(struct stack *ss, int (*cmp)(const void*, const void*))
{
    struct stack *min = ss;
    for (struct stack *sp = ss; sp; sp = sp->next)
        if (cmp(sp->data, min->data) < 0)
            min = sp;
    
    return min;
}

void stack_sort(struct stack *ss, int (*cmp)(const void*, const void*))
{
    if (!ss) return;
    
    for (struct stack *sp = ss; sp; sp = sp->next) {
        struct stack *min = stack_find_min(sp, cmp);
        swap(&sp->data, &min->data);
    }
}

swap() swaps two pointers:

void swap(void **p1, void **p2)
{
    void *tmp = *p1;
    *p1 = *p2;
    *p2 = tmp;
}

After that, define your student data structure:

struct student {
    unsigned long rollnumber;
    char name[100];
    struct student *next;
};

struct student *student_insert(struct student **head, unsigned long rollnumber, const char *name)
{
    struct student *st = malloc(sizeof(*st));
    if (!st) return NULL;
    
    st->rollnumber = rollnumber;
    strncpy(st->name, name, 99);
    st->next = *head;
    *head = st;
    
    return st;
}

void student_print(const struct stack *ss)
{
    struct student *st = ss->data;
    printf("%ld\t%s\n", st->rollnumber, st->name);
}

int student_compare_id(const void *s1, const void *s2)
{
    // MUST cast void* into (struct student*) first.
    const struct student *student1 = s1;
    const struct student *student2 = s2;
    
    unsigned long rollnumber1 = student1->rollnumber;
    unsigned long rollnumber2 = student2->rollnumber;
    
    unsigned long id1 = rollnumber1 % 10000;
    unsigned long id2 = rollnumber2 % 10000;
    
    return id1 == id2 ? 0 : (id1 < id2 ? -1 : 1);
}

If you want to test the above:

int main(void)
{
    struct stack *ss;
    stack_init(&ss);

    struct student *st = NULL;
    student_insert(&st, 100181234, "James");
    student_insert(&st, 200195678, "John");
    student_insert(&st, 300200324, "Goku");
    student_insert(&st, 400214321, "Taylor");
    
    for (struct student *p = st; p; p = p->next)
        stack_push(&ss, p);

    puts("Unsorted stack:");    
    stack_print(ss, student_print);
    
    stack_sort(ss, student_compare_id);
    
    puts("\nSorted by ID:");
    stack_print(ss, student_print);

    // Don't forget to free the memory allocated for students
    // and pop all nodes of the stack (ommited here).
}

Output:

Unsorted stack:
100181234   James
200195678   John
300200324   Goku
400214321   Taylor

Sorted by ID:
300200324   Goku
100181234   James
400214321   Taylor
200195678   John

Few more things:

  • Don't use scanf() to read user input. fgets() is safer.
  • You can replace pow(10, 4) directly by 10000. Why wasting CPU cycles to calculate constants?
  • In your insert() function, there is no need to test for *head == NULL. The code in the else statement handles this case.

EDIT: In student_compare_id(), the const void* pointers MUST BE CASTED to const struct student* first before dereferencing. The previous version seemed to work because the rollnumber happened to be the first field in the struct. That was an undefined behavior in all its glory. Fixed that now.

Here is the previous version that NO ONE SHOULD USE:

int student_compare_id(const void *s1, const void *s2)
{
    unsigned long rollnumber1 = *(unsigned long*)s1; // WRONG!
    unsigned long rollnumber2 = *(unsigned long*)s2; // WRONG!
    
    unsigned long id1 = rollnumber1 % 10000;
    unsigned long id2 = rollnumber2 % 10000;
    
    return id1 == id2 ? 0 : (id1 < id2 ? -1 : 1);
}
紫南 2025-01-28 13:05:17

主要问题是您的堆栈和学生列表之间没有连接,但是代码假定存在。您可以根据需要重新排序堆栈,但这不会重新排序列表。当您打印时,学生只是以插入顺序反向出现(因为您在列表的前面插入,然后从前到后面遍历列表)。

您有两个主要的选择:

  1. 将列表和所有堆栈组合到一个链接列表中。如果您愿意,可以使用列表风格和堆栈风格。或

  2. 将堆栈节点指向相应的列表元素,并在打印堆栈时穿越这些元素,以使学生按堆栈隐含的顺序获取。

The primary problem is that there is no connection between your stack(s) and your student list, but the code assumes that there is. You can reorder the stacks however you like, but that does not reorder the list. When you print, the students simply come out in the reverse of their insertion order (because you insert at the front of the list, and then traverse the list from front to back).

You have two main alternatives:

  1. combine the list and all the stacks into one linked list. You can use this both list-style and stack-style if you like. OR

  2. Give the stack nodes pointers to the corresponding list elements, and traverse those when you print a stack to get the students in the order implied by the stack.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文