【问题标题】:Insert function for linked list in descending order of insertion - only head node permited按插入降序插入链表的函数 - 只允许头节点
【发布时间】:2019-07-28 21:46:24
【问题描述】:

我的任务是用 C 语言创建一个将用户输入插入简单链表的程序,但有以下限制:

  • 节点必须按降序排序;
  • 只允许使用头节点监控(不允许监控尾节点)。

这是我的插入函数的当前代码:

void insert(struct snode *node, struct snode *aux) {
    if (aux) {
        if (node->n >= monitor.head->n) {
            node->next = monitor.head;
            monitor.head = node;
            return;
        }
        if (node->n < aux->n) {
            node->next = aux->next;
            aux->next = node;
            return;
        } else
            insert(node, aux->next);
    }
}

我遇到的问题是:如果我输入,例如:5 然后9 然后1,列表最终将被排序为9 -> 1 -> @987654327 @ -> NULL,应该是9 -> 5 -> 1 -> NULL。我在这里错过了什么?因为我尝试了我能想到的一切。

这是完整的程序,以防有帮助:

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

/* GLOBAL VARS */
struct snode {
    int n;
    struct snode *next;
};
struct smonitor {
    struct snode *head;
} monitor;

/* FUNCTION PROTOTYPING */
void insert(struct snode *node, struct snode *aux);
void search(int s, struct snode *aux);
struct snode *aloc(int p);
void print(struct snode *aux);
void readInputFile();

/* MAIN LOOP */
int main() {
    int p, s;
    int opt;
    _Bool endMain = 1;
    while (endMain == 1) {
        struct snode *aux = monitor.head;
        printf("Define Option:\n0-Exit\n1-Insert\n2-Search\n3-Print\n");
        scanf("%d", &opt);
        switch (opt) {
          case 0:
            endMain = 0;
            break;
          case 1:
            printf("Define node:\n");
            scanf("%d", &p);
            struct snode *node = aloc(p);
            if (monitor.head == NULL)
                monitor.head = node;
            else
                insert(node, aux);
            break;
          case 2:
            printf("Define search term:\n");
            scanf("%d", &s);
            search(s, aux);
            break;
          case 3:
            printf("List is:\n");
            print(aux);
            printf("[NULL]\n");
            break;
          case 4:
            readInputFile();
            break;
          default:
            printf("INVALID OPTION\n");
        }
    }
    return 0;
}

/* FUNCTIONS */
void insert(struct snode *node, struct snode *aux) {
    if (aux) {
        if (node->n >= monitor.head->n) {
            node->next = monitor.head;
            monitor.head = node;
            return;
        }
        if (node->n < aux->n) {
            node->next = aux->next;
            aux->next = node;
            return;
        } else
            insert(node, aux->next);
    }
}

void search(int s, struct snode *aux) {
    if (aux) {
        if (s == aux->n)
            printf("HIT - Node %d found\n", aux->n);
        else
            search(s, aux->next);
    } else
        printf("NO HIT - Node not found\n");
}

struct snode *aloc(int p) {
    struct snode *node;
    node = (struct snode *)malloc(sizeof(struct snode));
    node->n = p;
    node->next = NULL;
    return node;
}

void print(struct snode *aux) {
    if (aux) {
        printf("[%d]-", aux->n);
        print(aux->next);
    }
}

void readInputFile() {
     FILE *fp;
     int input;
     struct snode *p;
     struct snode *aux;

     fp = fopen("/home/user/inputFile.txt", "r");
     printf("Nodes added:\n");
     while (fscanf(fp, "%d", &input) != EOF) {
         p = aloc(input);
         aux = monitor.head;
         if (monitor.head == NULL)
             monitor.head = p;
         else
             insert(p, aux);
         printf("[%d]-", input);
    }
    printf("\n");
    fclose(fp);
}

提前感谢你们提供的任何帮助! :D

/------------------编辑----------- -------------------------/ 在你们的反馈和一些测试之后,我设法找到了一个解决方案,可能不是它的最佳实现,并且还有其他不同实现的答案(非常感谢!:))在那里,但这是该插入的新版本功能,再次感谢大家的提示! :D

void insert (struct snode *node, struct snode *aux, struct snode *pre){
    if(aux){
        if(node->n >= monitor.head->n){
            node->next = monitor.head;
            monitor.head = node;
            return;
        }
        if((pre->n >= node->n) & (node->n >= aux->n)){
            pre->next = node;
            node->next = aux;
            return;
        }
        if((pre->n >= node->n) & (aux->next == NULL)){
            aux->next = node;
            return;
        }
        insert(node, aux->next, aux);
    }
}

【问题讨论】:

  • 我想尽了所有办法。”:你有没有想过用调试器单步调试你的代码?

标签: c linked-list singly-linked-list


【解决方案1】:

由于insert()代码的这一部分而出现问题:

        if(node->n < aux->n){      // <=========
                node->next = aux->next;
                aux->next = node;
            ....
            ....

插入顺序为591。当你插入1时,那个时候链表就是

-------      -------
|  9  |----->|  5  |
-------      -------

node-&gt;n 的值为1aux-&gt;n 的值为9。因此,if 条件的比较被评估为true

if(node->n < aux->n){

在节点9 之后插入值1 的节点,您将获得序列915

【讨论】:

  • 他也没有在我能看到的任何地方初始化monitor.head
  • @MikeHolt monitor.headmain() 中初始化 switch case 1
  • @H.S.谢谢回复!关于如何使函数确保将节点插入正确位置的任何想法?我虽然在下一个函数调用中设置 aux = aux->next 之前将第三个参数设置为 arg = aux,然后将该 if 语句修改为 if((node->n > aux->n) & (node->n n)),我会在这里尝试,但你觉得呢?
  • @RefriDeLagosta 是的,将aux 作为第三个参数传递应该可以。大概insert() 代码是,假设insert() 函数prev 的第三个参数的名称将接收aux 值(第一个和第二个参数名称未更改),-if (aux-&gt;n &lt; node-&gt;n) { node-&gt;next = aux; if (prev) prev-&gt;next = node; if (aux == monitor.head) monitor.head = node;} else {insert(node, aux-&gt;next, aux);}。请注意,您的代码有改进的余地。你可以用更好的方式来写它。
  • @chqrlie 在我之前的评论之一中,我曾向 OP 提到过 - “您的代码有改进的余地。您可以用更好的方式编写它。”我特意把这个任务留给了OP。
【解决方案2】:

insert 中的测试不正确。除了这个 fis,您不应该使用全局变量 monitor 并让 insert 和其他函数修改它会造成混淆,并违背将列表作为参数传递的目的。

这是修改后的版本:

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

/* STRUCTURES */
struct snode {
    int n;
    struct snode *next;
};
struct smonitor {
    struct snode *head;
};

/* FUNCTION PROTOTYPES */
void insert(struct snode *node, struct smonitor *mon);
void search(int s, struct smonitor *mon);
struct snode *aloc(int p);
void print(struct smonitor *mon);
void readInputFile(struct smonitor *mon);
int flush(void);

/* MAIN LOOP */
int main() {
    int p, s;
    int opt;
    struct smonitor monitor = { NULL };
    _Bool endMain = 0;

    while (!endMain) {
        printf("Define Option:\n0-Exit\n1-Insert\n2-Search\n3-Print\n");
        if (scanf("%d", &opt) != 1)
            break;
        switch (opt) {
          case 0:
            endMain = 1;
            break;
          case 1:
            printf("Define node:\n");
            if (scanf("%d", &p) != 1) {
                flush();
                break;
            }
            struct snode *node = aloc(p);
            if (node == NULL) {
                fprintf(stderr, "allocation failure\n");
                break;
            }
            insert(node, &monitor);
            break;
          case 2:
            printf("Define search term:\n");
            if (scanf("%d", &s) != 1) {
                flush();
                break;
            }
            search(s, &monitor);
            break;
          case 3:
            printf("List is:\n");
            print(&monitor);
            break;
          case 4:
            readInputFile(&monitor);
            break;
          default:
            printf("INVALID OPTION\n");
            break;
        }
    }
    return 0;
}

/* FUNCTIONS */

int flush(void) {
    int c;
    while ((c = getchar()) != EOF && c != '\n')
        continue;
    return c;
}

void insert(struct snode *node, struct smonitor *mon) {
    struct node *aux;
    if (mon->head == NULL || node->n > mon->head->n) {
        node->next = mon->head;
        mon->head = node;
        return;
    }
    aux = mon->node
    while (aux->next && node->n <= aux->next->n) {
        aux = aux->next;
    }
    node->next = aux->next;
    aux->next = node;
}

void search(int s, struct smonitor *mon) {
    struct snode *aux = mon->head;
    while (aux) {
        if (s == aux->n) {
            printf("HIT - Node %d found\n", aux->n);
            return;
        }
        aux = aux->next;
    }
    printf("NO HIT - Node not found\n");
}

struct snode *aloc(int p) {
    struct snode *node;
    node = (struct snode *)malloc(sizeof(struct snode));
    if (n != NULL) {
        node->n = p;
        node->next = NULL;
    }
    return node;
}

void print(struct smonitor *mon) {
    struct snode *aux = mon->head;
    while (aux) {
        printf("[%d]-", aux->n);
        aux = aux->next;
    }
    printf("[NULL]\n");
}

void readInputFile(struct smonitor *mon) {
     FILE *fp;
     int input;

     fp = fopen("/home/user/inputFile.txt", "r");
     if (fp == NULL) {
         fprintf(stderr, "cannot open file /home/user/inputFile.txt\n");
         return;
     }
     printf("Nodes added:\n");
     while (fscanf(fp, "%d", &input) == 1) {
         struct snode *p = aloc(input);
         if (p == NULL) {
             fprintf(stderr, "\nallocation failure\n");
             break;
         }
         insert(p, mon);
         printf("[%d]-", input);
    }
    printf("\n");
    fclose(fp);
}

【讨论】:

    【解决方案3】:

    插入逻辑, 只保证逻辑正确,不保证最优实现。如果链接很长,则无法使用递归。

    1. 如果 aux 是 head 并且 node 大于 aux,则将 node 插入到 头
    2. 如果 aux->next 为 null,则在末尾插入节点
    3. 如果节点大于 aux->next,则应在其间插入节点 aux 和 aux->下一个
    4. 否则将辅助放倒

    将插入函数改为

    void insert(struct snode *node, struct snode *aux)
    {
        if (aux) {
            if(aux == monitor.head && node->n >= aux->n) {
                node->next = monitor.head;
                monitor.head = node;
            } else if (!aux->next) {
                aux->next = node;
            } else if(node->n >= aux->next->n) {
                node->next = aux->next;
                aux->next = node;
            } else {
                insert(node, aux->next);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-11
      • 1970-01-01
      • 2018-04-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多