我正在尝试使用概率十分之一的方式从链接列表中删除随机元素。如何从链接列表中删除随机元素?基本上,在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;
}
答案 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