You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言如何将未排序链表过滤后无需预先排序直接按升序写入文件

数据结构作业问题解决方案

核心实现逻辑

作业要求写入文件前不能对原列表排序,我们可以通过构建临时有序链表实现需求,全程不会修改原链表的内容和顺序:

  • 遍历原链表,过滤掉所有需移除的元素(能被3整除、包含数字3)
  • 对每个符合保留条件的元素,创建新节点复制值后,按升序插入到临时链表中
  • 遍历完成后直接将临时有序链表的内容写入文件即可

修改后的完整代码

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#include<stdbool.h>
#define BUFFER_LENGTH 256

typedef struct lista* Poz;
typedef struct lista {
    int br;
    Poz next;
}lista;

bool containsDigit(int, int);
int PrintList(Poz);
int PrintRandom(int, int);
Poz StvoriCvor();
int PrintToFile(Poz);
// 新增:向有序链表插入元素的函数
int InsertSorted(Poz sortedHead, int num);

bool containsDigit(int number, int digit) {
    // 单独处理数字0的情况,避免进入循环直接返回false
    if (number == 0) {
        return digit == 0;
    }
    while (number != 0) {
        int curr_digit = number % 10;
        if (curr_digit == digit)
            return true;
        number /= 10;
    }
    return false;
}

int InsertSorted(Poz sortedHead, int num) {
    Poz newNode = StvoriCvor();
    if (newNode == NULL) {
        return -1;
    }
    newNode->br = num;
    // 寻找插入位置
    Poz curr = sortedHead;
    while (curr->next != NULL && curr->next->br < num) {
        curr = curr->next;
    }
    // 插入节点
    newNode->next = curr->next;
    curr->next = newNode;
    return 0;
}

int PrintToFile(Poz P) {
    int digit = 3;
    if (P == NULL) return -1;
    char* fileName = NULL;
    FILE* fp;

    fileName = (char*)malloc(sizeof(char) * BUFFER_LENGTH);
    if (fileName == NULL) return -1;

    printf("请输入文件名:\n");
    scanf("%s", fileName);

    fp = fopen(fileName, "w+");
    if (fp == NULL) {
        free(fileName);
        return -1;
    }

    // 初始化临时有序链表头
    lista sortedHead = {0, NULL};
    while (P != NULL) {
        if (!(P->br % 3 == 0 || containsDigit(P->br, digit) == true)) {
            // 符合保留条件的元素插入有序链表
            InsertSorted(&sortedHead, P->br);
        }
        P = P->next;
    }

    // 将有序链表写入文件
    Poz temp = sortedHead.next;
    while (temp != NULL) {
        fprintf(fp, "%d\n", temp->br);
        // 写入后释放临时节点内存
        Poz toFree = temp;
        temp = temp->next;
        free(toFree);
    }

    fclose(fp);
    free(fileName);
    return 0;
}

int PrintRandom(int min, int max) {
    int num = (rand() % (max - min + 1) + min);
    return num;
}

int PrintList(Poz P) {
    P = P->next;
    if (P == NULL) {
        printf("链表为空.\n");
    }
    else {
        printf("链表中的元素如下:\n");
        while (P != NULL) {
            printf("%d ", P->br);
            P = P->next;
        }
        printf("\n");
    }
    return 0;
}

Poz StvoriCvor() {
    Poz Q = NULL;
    Q = (Poz)malloc(sizeof(lista));
    if (Q == NULL) {
        printf("创建节点失败.\n");
        return NULL;
    }
    Q->next = NULL;
    return Q;
}

int main() {
    lista head;
    head.next = NULL;
    Poz Q = NULL;
    int min = 0, max = 100, count = 30;
    srand(time(0));

    for (int i = 0; i < count; i++) {
        Q = StvoriCvor();
        if (Q == NULL) {
            printf("创建节点失败.\n");
        }
        else {
            Q->br = PrintRandom(min, max);
            // 这里如果要严格按生成顺序存链表,应该用尾插,原代码是头插会倒序,需要的话可以修改为尾插
            Q->next = head.next;
            head.next = Q;
        }
    }
    PrintList(&head);
    PrintToFile(head.next);

    // 释放原链表内存,避免泄漏
    Poz temp = head.next;
    while (temp != NULL) {
        Poz toFree = temp;
        temp = temp->next;
        free(toFree);
    }

    return 0;
}

额外优化说明

  • 修复了containsDigit函数对数字0的判断逻辑漏洞
  • 补充了所有动态分配内存的释放逻辑,避免内存泄漏
  • 将原代码中的克罗地亚语提示替换为中文,更便于阅读
  • 原代码生成链表用了头插法,存入顺序和生成顺序相反,如果需要严格符合"按生成顺序存入链表"的要求,可以修改为尾插法实现

内容的提问来源于stack exchange,提问作者duje.je

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 02:45:01