在不使用struct的情况下实现动态链表

时间:2020-06-12 01:32:23

标签: c arrays data-structures linked-list dynamic-memory-allocation

我正在寻找有关创建非常特定类型的双向链接列表的建议。这不是分配。每个节点都是一个C的整数指针数组。

Node Structure:
0: [back pointer "<-"]
1: [forward pointer "->"]
2: [data pointer "="]

列表的结构为:

Linked List:

head->n0
n0[head<-][->n1][=10]
n1[n0<-][->n2][=11]
n2[n1<-][->tail][=12]
n2<-tail

我将如何使用stdlib的malloc()在C语言中创建此结构?

1 个答案:

答案 0 :(得分:0)

您需要一个数据节点(结构数据节点),该节点记录数据数组的大小和当前长度。当您添加元素时,我们允许此数组动态增长。此解决方案从双向链接列表节点拆分数据数组。

注意:为简洁起见,我省略了“ struct”;固定左为练习。

/***
  Node Structure:
  0: [back pointer "<-"]
  1: [forward pointer "->"]
  2: [data pointer "="]
  Where the structure of the list is:

Linked List:
head->n0
n0[head<-][->n1][=10]
n1[n0<-][->n2][=11]
n2[n1<-][->tail][=12]
n2<-tail
 ***/

struct datanode {
    int size; // size of array allocated
    int len;  // number of elements assigned
    int ray[1]; // array[size], array[0..len] valid
};

datanode*
datanode_new(int size) {
    data_node* np = malloc( sizeof(data_node)+sizeof(int)*(size-1) );
    if( !np ) return(np);
    np->size = size;
    return(np)l
}
int
datanode_free(datanode* np) {
    if( !np ) return(-1);
    int size = np->size;
    free(np);
    return(size);
}
datanode*
datanode_resize(datanode* np, int size) {
    datanode* newp;
    if( !np ) {
        newp = datanode_new(size);
        return(newp);
    }
    if( size == np->size ) return(np); // no change
    newp = datanode_new(size);
    if( !newp ) return(np);
    for( int ndx = 0; ndx < min(size,np->len); ++ndx ) {
        newp->ray[ndx] = np->ray[ndx];
    }
    free(np);
    return(newp);
}
datanode*
datanode_copy(datanode* np, datanode* dp) {
    datanode* newp=NULL;
    if( !np ) return(dp);
    if( !dp ) return(dp);
    for( int ndx = 0; ndx < min(dp->size,np->len); ++ndx ) {
        dp->ray[ndx] = np->ray[ndx];
    }
    return(newp);
}
datanode*
datanode_dup(datanode* np) {
    datanode* newp=NULL;
    if( !np ) return(newp);
    newp = datanode_new(np->size);
    if( !newp ) return(newp);
    datanode_copy(np, newp);
    return(newp);
}
int
datanode_size(datanode* np) {
    if( !np ) return(-1);
    return(np->size);
}
int
datanode_set(datanode* np, unsigned int index,int val) {
    if( !np ) return(-1);
    if( index <= np->size ) { np->ray[index] = val; }
    return(index);
}
// autoexpand (double when reach capacity)
int
datanode_add(datanode* np,int val) {
    if( !np ) return(-1);
    if( np->len >= np->size ) {
        datanode* newp = datanode_resize(np->size*2);
    }
    int len = np->len;
    if( np->len < np->size ) {
        np->ray[np->len++] = val;
        return(len);
    }
    else { return(-1); }
    return(len);
}
int
datanode_valid(datanode* np, unsigned int index) {
    if( !np ) return(-1);
    if( index <= np->len ) return(0);
    return(-1);
}
int
datanode_at(datanode* np, unsigned int index) {
    if( !np ) return(-1);
    if( index <= np->len ) return(np->ray[index]);
    return(-1);
}

然后,您需要一个双链列表节点;父指针用于提供检测头/尾的机制并提供头/尾结构的维护。

struct my_dnode {
    my_dnode* prev;
    my_dnode* next;
    void* parent;   //not NULL when head or tail
    datanode* data;
};

my_dnode*
mydnode_new(int size) {
    my_dnode* dn = malloc( sizeof(my_dnode) );
    if( !dn ) return(ln);
    dn->prev = NULL;
    dn->next = NULL;
    dn->parent = NULL;
    dn->data = datanode_new(size);
    return(dn);
}
// only reasonable to delete node once removed from list
my_dnode*
mydnode_free(my_dnode* dn) {
    if( !dn ) return(dn);
    if( dn->prev ) return(dn->prev);
    if( dn->next ) return(dn->next);
    if( dn->data ) {
        datanode_clear(dn->data);
        datanode_free(dn->data);
        dn->data = NULL;
    }
    return(ln);
}
my_dnode*
mydnode_prev(my_dnode* np) {
    if( !np ) return(np);
    return(np->prev);
}
my_dnode*
mydnode_next(my_dnode* np) {
    if( !np ) return(np);
    return(np->next);
}
// after after current node np, append node xp
my_dnode*
mydnode_append(my_dnode* np, my_dnode* xp) {
    if( !np ) return(np);
    if( !xp ) return(xp);
    xp->next = np->next;
    xp->prev = np;
    if( np->next ) { np->next->prev = xp; }
    np->next = xp;
    // if( np->parent ) { need to fix tail }
    return(xp);
}
// before current node np, insert node xp
my_dnode*
mydnode_insert(my_dnode* np, my_dnode* xp) {
    if( !np ) return(np);
    if( !xp ) return(xp);
    xp->prev = np->prev;
    xp->next = np;
    if( np->prev ) { np->prev->next = xp; }
    np->prev = xp;
    // if( np->parent ) { need to fix head }
    return(xp);
}
// extract node xp at current node np
my_dnode*
mydnode_extract(my_dnode* np) {
    if( !np ) return(np);
    my_dnode* xp = np; // extract node
    // if( xp->parent ) { need to fix head or tail }
    if( np->prev ) { np->prev->next = np->next; }
    if( np->next ) { np->next->prev = xp->prev; }
    xp->next = NULL;
    xp->prev = NULL;
    return(xp);
}
// drop next node after current node np
my_dnode*
mydnode_drop(my_dnode* np, my_dnode* xp) {
    if( !np ) return(np);
    if( np->next ) { return(mydnode_extract(np->next); }
    my_dnode* xp = np; // this node
    return(mydnode_extract(xp));
}
// pop previous node before current node
my_dnode*
mydnode_pop(my_dnode* np, my_dnode* xp) {
    if( !np ) return(np);
    if( np->prev ) { return(mydnode_extract(np->prev); }
    my_dnode* xp = np; // extract node
    return(mydnode_extract(xp));
}

您(可能)想要一个拥有列表头部和尾部的父级列表结构,以简化对列表结构的跟踪。

struct my_dlist {
    my_dnode* head;
    my_dnode* tail;
    int size; //default size
    int val;  //default value
};

my_dlist*
dlist_new(int size, int value) {
    my_dlist dp = malloc( sizeof(my_dlist) );
    if( !dp ) return(dp);
    dp->head = NULL;
    dp->tail = NULL;
    dp->size = size;
    dp->val = value;
    return(dp);
}
int
dlist_del( my_dlist* dp, int size, int value) {
    if( !dp ) return(-1);
    if( dp->head ) return(-2); //error
    if( dp->tail ) return(-3); //error
    dp->size = 0;
    dp->val = 0;
    return(0);
}
int
ln_append(my_dlist* dp, datanode* np) {
    if( !dp ) return(-1);
    if( !np ) return(-2);
    np->prev = dp->tail;
    dp->tail = np;
    // if( np->parent ) { need to fix tail }
    return(0);
}
int
ln_insert(my_dlist* dp, datanode* np) {
    if( !dp ) return(-1);
    if( !np ) return(-2);
    np->next = dp->head;
    dp->head = np;
    // if( np->parent ) { need to fix head }
    return(0);
}
datanode*
ln_head(my_dlist* dp) {
    if(!dp) return(NULL);
    return(dp->head);
}
datanode*
ln_tail(my_dlist* dp) {
    if(!dp) return(NULL);
    return(dp->tail);
}