c - 删除链表元素

标签 c linux linked-list

我很好奇我做错了什么,因为我的 void *DeleteDoneNodes(node * n) 没有做任何事情,没有错误但没有输出更晚,所以任何人都可以帮我找到我的问题的根源谢谢你。

场景:命令行 ./s m n m 列表中的节点数,n workingThreads 的数量应该删除每个具有 node->value == 1 的节点,但它不会做任何事...

代码:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <math.h>
#include <semaphore.h>

#define finishedNodes 5
#define workersLimitNr 3

int workingThreads = 0;
sem_t sem;

struct dataBlock{
    struct node *root;
    int listSize;
    int forIndex;
};

struct node { // std linked list node
    int value;
    int worker;
    struct node *next;
};

int slots = 0; // only 3 threads are allowed to access the list
int availableCheck(){   // check if thread can acces the list
    if(slots < 3) 
        return 0;
    else 
        return -1;
}



pthread_mutex_t mutp = PTHREAD_MUTEX_INITIALIZER;   // mutex
pthread_cond_t  condvar = PTHREAD_COND_INITIALIZER;   //condvar

void *deleteDoneNodes(struct node *n){ // T H I S  I S  T H E  F U N C
        struct node *root = n;
        struct node *it;
        it = root;
        do{
            if(it->value == 1){
                struct node *tmp;
                printf("DELETING: %d > %d\n", it->value, it->worker );
                root = root->next;
                tmp = it;
                it = it->next;
                free(tmp);
            }
            else
                it = it->next;
    }while(it !=  NULL);

    return NULL; 
}

void * worker( void *data ){
    struct dataBlock *inData = (struct dataBlock *) data;
    struct node *root = inData->root;
    int forIndex = inData ->forIndex;
    free(data);
    printf( "*    Thread id: %lu    forID:  %d  workerNode: \n",pthread_self(),forIndex); 

    pthread_mutex_lock( &mutp );
    if(availableCheck() < 0){
        printf( " ^^^ List not available yet... \n" ); 
        pthread_cond_wait( &condvar, &mutp ); 
    } 
    struct node *it = root;

    printf( " _forID_ %d\n |", forIndex );  
    do{
        if(forIndex == it->worker){
            printf("valid for sqrt  forIndex %d == it->worker %d\n",forIndex, it->worker );
            if(it->value > 2){
                while(it->value != 1)
                it->value = sqrt(it->value);
                // it->value = it->value - 1;
            }
        }
        it = it->next;
    }while(it !=  NULL);

    pthread_cond_signal( &condvar ); // 
    pthread_mutex_unlock( &mutp ); 
    return NULL;
}

int main( int argc, char *argv[] ){
    if ( argc != 3 ){
        printf( "Programm must be called with \n NR of elements and NR of workers! \n " );
        exit( 1 );
    }

    int i;
    struct node *root;
    struct node *iterator;  

//prepare list for task
    int listSize = atoi(argv[1]);
    int nrWorkers = atoi(argv[2]);
    root = malloc(sizeof( struct node) );

    root->value = rand() % 100;
    root->worker = 0;
    iterator = root;

    for( i=1; i<listSize; i++ ){
        iterator->next = malloc(sizeof(struct node));
        iterator = iterator->next;
        iterator->value = rand() % 100;
        iterator->worker = i % nrWorkers;
        printf("node #%d worker: %d  value: %d\n", i, iterator->worker,iterator->value);
    }
    iterator->next = NULL;
    printf("? List got populated\n");
// init semaphore > keeps max 3 threads working over the list

    if( sem_init(&sem,0,3) < 0){
      perror("semaphore initilization");
      exit(0);
    }

// Create all threads to parse the link list
    int ret;    
    pthread_mutex_init(&mutp,NULL);

    pthread_t w_thread;
    pthread_t* w_threads = malloc(nrWorkers * sizeof(w_thread));

    for( i=0; i < nrWorkers; i++ ){         
        struct dataBlock *data = malloc(sizeof(struct dataBlock));
        data->root = root;
        data->listSize = listSize;
        data->forIndex = i;
        ret = pthread_create ( &w_threads[i], NULL, worker, (void *) data );
        if( ret ) {
            perror("Thread creation fail");
            exit(2);    
        }   
    } 

    deleteDoneNodes( root );
    // printf( ">>>> %d\n", root->value );
    for ( i = 0; i < nrWorkers; i++ ){
        pthread_join(w_threads[i],NULL);
    }
    // for ( i = 0; i < nrWorkers; i++){
    //  free(w_threads);
    // }

    iterator = root;
    for ( i = 0; i < listSize; i++){
        printf("val: %d  worker: %d _  ", iterator->value, iterator->worker);
        iterator = iterator->next;
    }

    free(root);
    free(iterator);
    return 0;
}

PS:它编译/工作错误/warningless - 也用 valgrind 测试。

最佳答案

这是一个替代版本

void *deleteDoneNodes(struct node *n){
    struct node *root = n;
    struct node *it = root;
    struct node *prev = NULL;
    do{
        if(it->value == 1){
            struct node *next = it->next;
            if (prev != NULL) {
                prev->next = next;
            }
            if (it == root) {
                root = next;
            }
            free(it);
            it = next;
        }
        else {
            prev = it;
            it = it->next;
        }
    }while(it !=  NULL);

    return root;
}

主要变化是:

  • 处理从列表中间删除一个项目。前一项需要更改其 next 指针。没有这个,它会一直指向释放的内存。
  • 更新 root 的逻辑。这只需要在我们释放 root
  • 时发生
  • 传达 root 中可能发生的变化。如果我们从列表中删除根(又名头)项,则需要将其传达给调用者。我通过返回 root 的(可能更新的)值而不是 NULL
  • 来完成此操作

关于c - 删除链表元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13742127/

相关文章:

c++ - 为什么我们需要在运行时使用函数指针调用这些函数。我们也可以直接调用他们

C 链表 - 指针值变化

java - 如何根据姓氏对链接列表进行排序?

调用同一个程序实例?

c - 防止孙子在 C 中 fork

linux - 在 gcc 版本 4.1.2 中出现错误 "unrecognized option -Xa "

linux - 如何在 shell 中创建别名以转到父目录

c - 指向链表指针的指针

c - 以 64 位整数为模计算 128 位整数的最快方法

java - 在linux中使用java web服务进行IPC(进程间通信)