我正在寻找有关创建非常特定类型的双向链接列表的建议。这不是分配。每个节点都是一个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语言中创建此结构?
答案 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);
}