您的位置:首页 > 其它

相对静态的链表实现

2011-04-30 10:14 169 查看
 

链表可以快速实现插入、删除节点,但是传统的链表实现在每次新建节点时都会malloc,经过glibc再经过申请内存空间的系统调用非常浪费时间,释放的时候还会造成内存空洞。

我想能否通过一次malloc预先分配足够的空间,之后自己维护链表需要的内存空间就不用频繁malloc了,制成一个相对“静态”的链表。

链表的结构如下定义:

enum states {STATE_FREE, STATE_IN_USED};
struct linkedListNode
{
int next;
int value;
int state;
};
struct linkedList
{
struct linkedListNode *arr;
int head;
int tail;
int size;
int capacity;
};
 

每个节点由一个int来指定下一个节点的index,而不是用传统的指针,描述链表大小的有size(节点的实际数量)和capacity(能存放节点的总数)

 

要想获得一个新的链表,首先需要给出链表的容量并初始化它:

struct linkedList *linkedListInitialize(int capacity)
{
int i;
struct linkedList *p = (struct linkedList *)malloc(sizeof(struct linkedList));
if (p == NULL) return 0;
p->capacity = capacity;
p->size = 0;
p->arr = (struct linkedListNode *)malloc(capacity * sizeof(struct linkedListNode));
if (p->arr == NULL)
{
free(p);
return 0;
}
for (i = 0; i < p->capacity; i++)
{
p->arr[i].next = -1;
p->arr[i].value = 0;
p->arr[i].state = STATE_FREE;
}
p->head = -1;
p->tail = -1;
return p;
}
 

 

删除链表的时候也很方便,把节点和链表本身都free了就行:

void linkedListFree(struct linkedList *p)
{
free(p->arr);
free(p);
p = NULL;
}
 

 

如何在链表中新获取一个可用节点呢?通过getFreeNode函数,这个函数应该有更高效的实现方法,为了简单期间我只是从头到尾遍历所有空间并且寻找可用节点后返回,如果找不到咋办?你可以选择创建一个新的更大的链表并转移数据,或者realloc,我这里时直接返回-1。

int getFreeNode(struct linkedList *p)
{
/* the performance problem may caused by this function
* current free node seaching method is too simple and slow */
int i;
for (i = 0; i < p->capacity; i++)
{
if (p->arr[i].state == STATE_FREE) return i;
}
return -1;
}
 

 

 

有个前面的基础,对链表进行操作就很容易了,我这里只实现几个操作。

 

在尾部追加新节点:

void linkedListPushBack(struct linkedList *p, int val)
{
int cur = p->head;
int new_node = getFreeNode(p);
if (new_node == -1)
{
printf("New free node not found./n");
return;
}
p->arr[new_node].value = val;
p->arr[new_node].state = STATE_IN_USED;
p->tail = new_node;
if (p->head == -1) /* the linked list is empty */
{
p->head = new_node;
p->arr[new_node].next = -1;
}
else /* the linked list is not empty */
{
while (!(p->arr[cur].next == -1))
{
cur = p->arr[cur].next;
}
p->arr[cur].next = new_node;
p->arr[new_node].next = -1;
p->tail = new_node;
}
}
 

 

插入节点:

void linkedListInsert(struct linkedList *p, int loc, int val)
{
int cur = p->head, prev = p->head;
int new_node = getFreeNode(p);
if (new_node == -1)
{
printf("New free node not found./n");
return;
}
p->arr[new_node].value = val;
p->arr[new_node].state = STATE_IN_USED;
if (p->size == 0) /* the linked list is empty */
{
p->head = new_node;
p->tail = new_node;
p->arr[new_node].next = -1;
}
else if (loc == 0) /* the new node as the head */
{
p->arr[new_node].next = p->head;
p->head = new_node;
if (p->size == 0) p->tail = new_node;
}
else /* new node as other part except the head */
{
if (loc < p->size)
{
while (loc--)
{
prev = cur;
cur = p->arr[cur].next;
}
p->arr[prev].next = new_node;
p->arr[new_node].next = cur;
}
else /* push back */
{
while (!(p->arr[cur].next == -1))
{
cur = p->arr[cur].next;
}
p->arr[cur].next = new_node;
p->arr[new_node].next = -1;
p->tail = new_node;
}
}
p->size++;
}
 

 

删除节点:

void linkedListErase(struct linkedList *p, int loc)
{
int prev, cur;
if (loc == 0) /* remove the head */
{
prev = p->arr[p->head].next;
p->arr[p->head].next = -1;
p->arr[p->head].value = 0;
p->arr[p->head].state = STATE_FREE;
p->head = prev;
if (loc == 1) p->tail = -1;
}
else
{
prev = p->head;
cur = p->head;
while (loc--)
{
prev = cur;
cur = p->arr[cur].next;
}
p->arr[prev].next = p->arr[cur].next;
p->arr[cur].next = -1;
p->arr[cur].value = 0;
p->arr[cur].state = STATE_FREE;
if (loc < p->size - 1) p->tail = prev;
}
p->size--;
}
 

 

清空所有节点:

void linkedListClear(struct linkedList *p)
{
int i;
for (i = 0; i < p->capacity; i++)
{
p->arr[i].next = -1;
p->arr[i].value = 0;
p->arr[i].state = STATE_FREE;
}
p->head = -1;
p->tail = -1;
p->size = 0;
}
 

 

打印节点:

void linkedListPrint(struct linkedList *p)
{
int cur = p->head;
while(cur > -1)
{
printf("%d/n", p->arr[cur].value);
cur = p->arr[cur].next;
}
printf("/n");
}
 

 

这样就完成了这个链表的基本结构和几个基本操作,还有很多改进的余地,比如分配空节点等等地方。

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息