【问题标题】:How to move certain elements from linked list at the end of that list?如何从该列表末尾的链表中移动某些元素?
【发布时间】:2021-02-10 17:06:25
【问题描述】:

今天我试图制作一个程序,可以将 15 个随机值(从 100 到 120)输入到链表中。 那部分就像一个魅力。然后我从该列表中找到最大值和最小值,然后找到平均值。

我想将所有大于平均值的值移到该列表的末尾,我尝试使用函数 prebaci 来实现。 函数 unos 将所有元素放入列表中,函数 unosK 将所有元素放入列表末尾。程序进入无限循环,我不知道为什么。您能帮我将所有大于平均值 (107) 的值移到列表末尾吗? 我的代码:

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

typedef struct lista* Pozicija;
struct lista {
    int el;
    Pozicija next;
};

void unos(Pozicija P, int el);//input front
void ispis(Pozicija P);//print 
int mini(Pozicija P);//find min
int maxi(Pozicija P);//find max
void prebaci(Pozicija P,int x);//function for transfering at the end
void unosK(Pozicija P,int x);//input end

int main() {
    srand(time(0));
    struct lista L;
    L.next = NULL;
    int min,max, i,j;
    int prvi[21], drugi[15];
    int avg;

    
    for (i = 0;i < 21;i++) {
        prvi[i] = i + 100;
        printf("%d ", prvi[i]);
    }
    for (i = 0;i < 15;i++) {
        int temp = prvi[i];
        int random = rand() % 15;

        prvi[i] = prvi[random];
        prvi[random] = temp;
    }
    printf("\n\n");
    for (i = 0;i < 15;i++) {
        //printf("%d ",prvi[i]);
        unos(&L, prvi[i]);
    }

    printf("Ispis\n");
    ispis(L.next);

    printf("\n\n");
    min = mini(L.next);
    printf("Minqi:%d\n", min);

    printf("\n\n");
    max = maxi(L.next);
    printf("Miaxi:%d\n", max);

    printf("\n\n");
    avg = (min + max) / 2;
    printf("avg:%d\n", avg);

    printf("\n\n");
    printf("Prebacaj:\n");
    prebaci(&L, avg);
    ispis(L.next);

}
void unos(Pozicija P, int el) {
    Pozicija q;
    q = (Pozicija)malloc(sizeof(struct lista));

    q->el = el;
    q->next = P->next;
    P->next = q;
}
void ispis(Pozicija P) {
    while (P != NULL) {
        printf("%d ", P->el);
        P = P->next;
    }
}
int mini(Pozicija P) {
    int min;
    min = INT_MAX;

    while (P != NULL) {
        if (min > P->el) {
            min = P->el;
        }
        P = P->next;
    }
    return min;
}
int maxi(Pozicija P) {
    int max;
    max = INT_MIN;

    while (P != NULL) {
        if (max< P->el) {
            max = P->el;
        }
        P = P->next;
    }
    return max;
}
void prebaci(Pozicija P,int x) {
    P = P->next;
    Pozicija t;
    t = P;
    while (t != NULL) {
        if (t->el > x)
        {
            unosK(P, t->el);
            t = t->next;
        }
        else if (t->el <= x) {
            unos(P, t->el);
            t = t->next;
        }
        
    }

}
void unosK(Pozicija P,int x) {
    Pozicija q=NULL;
    q = (Pozicija)malloc(sizeof(struct lista));
    q->el = x;

    while (P->next != NULL)
            P = P->next;

    
    q->next = P->next;
    P->next = q;

}

【问题讨论】:

  • 如果你在一个链表上进行迭代并且不断地在链表的末尾添加元素,那么无限循环就不可避免了。
  • 您正在计算最小值和最大值的平均值,而不是整个列表的平均值。这是故意的吗?
  • @Jack Jones 为什么在循环中使用数字 15 而不是数字 21 for (i = 0;i
  • @Jack Jones 在列表中有一个虚拟节点(第一个节点)是个坏主意。
  • 您可以通过将大于平均的元素移动到新列表然后将新列表附加到旧列表的末尾来避免无限循环。

标签: c linked-list


【解决方案1】:

这是原始prebaci 函数的有效替代品。它仍然在列表的开头有一个虚拟节点,但没有分配任何新元素。

它不是调用分配新元素的unosunosK,而是操纵原始列表中的指针,将大于平均值的元素移动到列表末尾。

它首先将大于平均值的元素从原始列表移动到一个新的、最初为空的列表 (q),然后将原始列表的最后一个元素链接到新列表的第一个元素,这样所有的大于平均值的元素现在位于原始列表的末尾。

新列表 (q) 已实现为指针而不是虚拟节点。

该函数利用指向指针(pppq)的指针来操作原始列表和新列表中的链接。

void prebaci(Pozicija P,int x) {
    Pozicija *pp = &P->next; /* pointer to link in original list */
    Pozicija q = NULL; /* new list for elements greater than average */
    Pozicija *pq = &q; /* pointer to end link of new list */
    while (*pp != NULL) {
        if ((*pp)->el > x) {
            /* move element from original list to end of new list */
            *pq = *pp;  /* end of new list points to moved element */
            *pp = (*pp)->next; /* remove element from original list */
            pq = &(*pq)->next; /* update pointer to end link of new list */
        }
        else {
            /* do not move this element */
            pp = &(*pp)->next; /* advance to next link in original list */
        }
    }
    *pq = NULL; /* terminate the new list */
    *pp = q; /* append the new list to the end of the original list */
}

【讨论】:

  • 该代码将平均值作为第一个元素。我想你误会了先生。谢谢你的时间,我真的很感激,但我正在考虑让我的程序只在列表末尾移动更大的值。所以只有大于平均值 (107) 的值才应该在列表中。
  • @JackJones 代码将列表分成两半(不相等),这样所有小于或等于平均值​​的元素都在前半部分结束,所有大于平均值的元素结束下半场。
  • @JackJones 例如,将平均值设置为 107,则列表 100 103 102 113 112 108 114 109 105 106 104 101 111 110 107 将更改为 100 103 102 105 106 1034 1711 112 108 114 109 111 110。大于 107 的所有内容都已移至列表末尾。
  • 就是这样。我没有考虑过,哈哈,我在做很多其他的项目,所以我的大脑过度劳累,我失去了注意力。感谢您的时间和帮助!
猜你喜欢
  • 2011-06-22
  • 2023-03-17
  • 2019-09-15
  • 1970-01-01
  • 2017-07-10
  • 1970-01-01
  • 1970-01-01
  • 2016-06-16
  • 2014-02-23
相关资源
最近更新 更多