从链表中删除随机元素

时间:2018-12-07 01:33:52

标签: c

我正在尝试使用概率十分之一的方式从链接列表中删除随机元素。如何从链接列表中删除随机元素?基本上,在remove函数中,我尝试随机删除节点,但是我似乎无法理解我在这里做错了什么。

int kill = 0;
SDL_Surface *message;
TTF_Font *font;
SDL_Color textColor = { 0, 255, 255 };


void removing_by_mouse(struct blockhead_node ** blockhead_list, int mx, int my)
{
    struct blockhead_node * temp;

    while((*blockhead_list) != NULL)
    {
        printf("%d, %d\n", mx, my);

        if((*blockhead_list)->x + (*blockhead_list)->size >= mx && (*blockhead_list)->x  <= mx && (*blockhead_list)->y + (*blockhead_list)->size >= my && (*blockhead_list)->y  <= my)
        {

            temp=(*blockhead_list);
            (*blockhead_list)=(*blockhead_list)->next;
            free(temp);
            return;
        }
        blockhead_list=&(*blockhead_list)->next;

    }
}

void removing(struct blockhead_node ** blockhead_list)
{
    struct blockhead_node * temp;
    while((*blockhead_list) != NULL)
    {

        for(kill = rand()%10; kill < 10; kill++)
        {

            temp=(*blockhead_list);
            (*blockhead_list)=(*blockhead_list)->next;
            free(temp);
            return;

        }

        blockhead_list=&(*blockhead_list)->next;

    }
}


    case SDL_KEYDOWN:  // Handle a KEYDOWN event
    switch(event.key.keysym.sym)
        {
            case SDLK_ESCAPE:
            done = 1;
            break;
            case SDLK_p:
                pause = !pause;
                break;
            case SDLK_a:
                addheads(blockhead);
                break;
            case SDLK_r:
                removing(&blockhead);
                break;
        }

2 个答案:

答案 0 :(得分:0)

您不需要return。而且,循环的顺序被颠倒了。而且,您应该只使用 one 循环。

这里有一些清理过的代码[未测试]:

void
removing(struct blockhead_node **blockhead_list)
{
    struct blockhead_node *temp;

    for (int kill = rand() % 10; kill < 10; kill++) {
        temp = *blockhead_list;
        if (temp == NULL)
            break;
        *blockhead_list = temp->next;
        free(temp);
    }
}

注意:这只会修复您的代码,该代码会从列表的 front 中删除随机数量的节点。

这可能不是与从列表中的中删除随机节点相同,这是一个更困难的问题。


更新:

  

我不确定这是如何满足OP要求的:“我正在尝试以十分之一的概率删除块” –尽管我承认我不清楚他的意思。

这里有一些代码可以删除随机数的随机元素。再次,进行了测试:

void
remove1(struct blockhead_node **list,int index)
{
    struct blockhead_node *cur;
    struct blockhead_node *prev;
    struct blockhead_node *next;
    int curidx;

    prev = NULL;
    next = NULL;
    curidx = 0;
    for (cur = *list;  cur != NULL;  cur = next, ++curidx) {
        next = cur->next;
        if (curidx == index)
            break;
        prev = cur;
    }

    if (prev != NULL)
        prev->next = next;
    else
        *list = next;

    if (cur != NULL)
        free(cur);
}

void
removing(struct blockhead_node **blockhead_list)
{
    int count = 0;
    struct blockhead_node *temp;

    // count elements in list
    for (temp = *blockhead_list;  temp != NULL;  temp = temp->next, ++count);

    for (int kill = rand() % 10; kill > 0; kill--, --count) {
        if (count <= 0)
            break;
        int index = rand() % count;
        remove1(blockhead_list,index);
    }
}

答案 1 :(得分:0)

函数node *removeNodesWithProbability(node *head, double removeProbability)遍历链接列表,并以概率removeProbability决定是保留还是删除当前节点。我相信这就是OP的追求。我将注意到可以通过使用递归来更简洁地编写此函数。

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

typedef struct _node {
   int data;
   struct _node *next;
} node;

node *removeNodesWithProbability(node *head, double removeProbability)
{
    node *cur, *prev;

    /* remove from head with removeProbability */
    while(head != NULL && drand48() < removeProbability)
    {
        prev = head;
        head = head->next;
        free(prev);
    }

    if (head == NULL) return head;

    /* head survived removal, now consider the remaining nodes */
    /* set prev to head and cur to head->next */
    prev = head;
    cur = head->next;

    /* delete from cur with removeProbability */
    while(cur != NULL)
    {
        if (drand48() < removeProbability)
        {
            /* remove the current node by pointing prev->next to cur->next */
            prev->next = cur->next;
            free(cur);
            cur = prev->next;
        }
        else
        {
            prev = prev->next;
            cur = cur->next;
        }
    }
    return head;
}

int count_nodes(const node *head)
{
    int ct = 0;
    for(; head != NULL; head=head->next, ++ct) ; /*empty loop */

    return ct;
}

void print_list(const node *head)
{
    for(; head != NULL; head=head->next)
    {
        fprintf(stdout, "%d\n", head->data);
    }
}

int main(void)
{
    int i;
    node *head = NULL, *next=NULL;
    srand48(time(NULL));

    for(i=0; i < 10000; ++i)
    {
        head = malloc(sizeof(*head));
        head->data = i;
        head->next = next;
        next = head;
    }

    fprintf(stdout, "initial size of list: %d\n", count_nodes(head));

    head = removeNodesWithProbability(head, 0.10);

    fprintf(stdout, "size after removal: %d\n", count_nodes(head));

    return 0;
}

输出removeProbability=0.10。您的电话号码会有所不同。

  

列表的初始大小:10000

     

移除后的大小:8989