新闻中心

EEPW首页 > 嵌入式系统 > 牛人业话 > C语言的那些小秘密之链表(二)

C语言的那些小秘密之链表(二)

作者:时间:2015-04-11来源:网络收藏

  从main()函数开始,通过 DList* dlist = dlist_head_create();我们创建了一个头节点。值得注意的是,为了更加通用和符合实际需求,我们在此创建的存放的是结构,因为现实中在使用时,绝大部分都是存放结构的,而前一篇文章中我们创建单链表时我们存放的是数据,所以这一点读者是要引起注意的,接下来是一个for循环语句,在for循环语句中我们首先使用DStu* stu =(DStu*) malloc(sizeof(DStu));为stu分配了空间,这也是很多读者的一个易错点,不分配就使用下面的stu->score = i;语句,从而导致出错,如果读者对于指针还不是很了解的话可以看看我前面的文章《的那些小秘密之指针》,在往下看dlist_append(dlist, (void*)stu);语句,从函数名称我们也可以看出它的功能是在链表的末端添加结点的,在函数里面我们使用了一个if判断语句来看分配的结点是否成功,如果成功继续往下执行,如果失败则返回DLIST_RETURN_FAIL。对于第一次分配的节点我们使用了 thiz->head = node;语句使其变为头结点,在第二次调用dlist_append(dlist, (void*)stu)函数分配结点之后,由于头结点已经不再为空,那么跳过if(thiz->head == NULL)语句,执行以下语句:

本文引用地址:http://www.eepw.com.cn/article/272382.htm

  cursor = thiz->head;

  while(cursor != NULL && cursor->next != NULL)

  { cursor = cursor->next; }

  其功能为查找末端结点,然后使用 cursor->next = node; node->prev = cursor;语句来将刚刚创建的新结点node作为尾结点。main()函数中的for循环语句执行完之后就轮到了调用dlist_print(dlist, print_int)函数打印我们创建的双向链表保存的数据值了,在这里的时候我们用了前面我博客中提到的函数指针作为参数的使用,如果有对函数指针不熟悉的读者可以参考我之前写的一篇博客《的那些小秘密之函数指针》,到此读者应该都理解了上面的代码,但是其中有个值得注意的地方,那就是main()函数中使用dlist_append(dlist, (void*)stu);的时候,我们传递的是一个无类型的指针,在创建新结点的时候,我们使用了一句node->data =(DStu*)data;进行一个强制转换,使得链表中的数据域指向的就是我们使用DStu* stu =(DStu*) malloc(sizeof(DStu));所创建的空间。创建了空间之后当然要释放掉,所以接下来我们就添加一个释放功能模块。新添加的代码我们用红色部分来标记。以便于读者的阅读

#include <stdio.h>
#include <stdlib.h>

typedef enum _DListReturn
{
DLIST_RETURN_OK,
DLIST_RETURN_FAIL
}DListReturn;

typedef struct _DStu
{
int score;
}DStu;

typedef struct _DListNode
{
struct _DListNode* prev;
struct _DListNode* next;

DStu* data;

}DListNode;

typedef struct _DList
{
DListNode* head;
}DList;

typedef DListReturn (*DListPrintFunction)(void* data);

DListNode* dlist_node_create(void* data)
{
DListNode* node;
if((node = (DListNode*) malloc(sizeof(DListNode)))==NULL)
{
printf("分配空间失败!");
exit(0);
}

if(node != NULL)
{
node->prev = NULL;
node->next = NULL;
node->data =(DStu*)data;
}

return node;
}

DList* dlist_head_create(void)
{
DList* thiz;
if((thiz = (DList*)malloc(sizeof(DList)))==NULL)
{
printf("分配空间失败!");
exit(0);
}

if(thiz != NULL)
{
thiz->head = NULL;
}

return thiz;
}

DListReturn dlist_append(DList* thiz, void* data)
{
DListNode* node = NULL;
DListNode* cursor = NULL;

if((node = dlist_node_create(data)) == NULL)
{
return DLIST_RETURN_FAIL;
}

if(thiz->head == NULL)
{
thiz->head = node;

return DLIST_RETURN_OK;
}

cursor = thiz->head;
while(cursor != NULL && cursor->next != NULL)
{
cursor = cursor->next;
}

cursor->next = node;
node->prev = cursor;

return DLIST_RETURN_OK;
}

DListReturn dlist_prepend(DList* thiz, void* data)
{
DListNode* node = NULL;
DListNode* cursor = NULL;

if((node = dlist_node_create(data)) == NULL)
{
return DLIST_RETURN_FAIL;
}

if(thiz->head == NULL)
{
thiz->head = node;

return DLIST_RETURN_OK;
}

cursor = thiz->head;

if(thiz->head == cursor)
thiz->head = node;

node->next = cursor;
cursor->prev = node;

return DLIST_RETURN_OK;
}

DListReturn dlist_print(DList* thiz, DListPrintFunction print)
{
DListNode* iter = thiz->head;

while(iter != NULL)
{
print(iter->data);
iter = iter->next;
}
printf("n");
return DLIST_RETURN_OK;
}

DListReturn print_int(void* data)
{
DStu* ss=(DStu*)data;
printf("%dt ", ss->score);

return DLIST_RETURN_OK;
}

DListReturn dlist_node_destroy(DListNode* node)
{
if(node != NULL)
{
node->next = NULL;
node->prev = NULL;
free(node);
}

return DLIST_RETURN_OK;
}

DListReturn dlist_destroy(DList* thiz)
{
DListNode* iter = thiz->head;
DListNode* next = NULL;

while(iter != NULL)
{
next = iter->next;
dlist_node_destroy(iter);
iter = next;
}

thiz->head = NULL;
free(thiz);

return DLIST_RETURN_OK;
}

int main(int argc, char* argv[])
{
int i = 0;
int n = 10;

DList* dlist = dlist_head_create();
DStu* stu[7];

for(i = 0; i < 7; i++)
{
stu[i] =(DStu*) malloc(sizeof(DStu));
stu[i]->score = i;
dlist_append(dlist, (void*)stu[i]);
}

dlist_print(dlist, print_int);

for(i = 0; i < 7; i++)
{
free(stu[i]);
}
return 0;
}

  在使用dlist_append(dlist, (void*)stu[i]);语句的时候我们传递的是stu[i]的指针,所以在创建结点的时候我们使用的node->data =(DStu*)data;语句使得data强制转换为了DStu结构类型指针,即在结点创建函数中我们仅仅是使数据域的结构指针data指向了stu[i]所分配的存储空间,和stu[i]指向的是同一个空间,但是在释放结点时,我们仅仅是释放掉了存放data指针变量的空间,并没有释放掉data所指向的空间,所以我们在main函数中我们最后使用了一个for循环语句来释放data所指向的存储空间。在此也讲讲之前我给出的以下代码和我们双链表释放方式的区别。

  #include

  #include

  int main()

  {

  int *pointer_1=(int *)malloc(sizeof(int));

  int *pointer_2=(int *)malloc(sizeof(int));

  pointer_1=pointer_2;

  printf("%dn",pointer_1);

  printf("%dn",pointer_2);

  printf("%dn",&pointer_1);

  printf("%dn",&pointer_2);

  //free(pointer_1);

  free(pointer_2);

  return 0;

  }

  运行结果为:

  

 

  3674136

  3674136

  1245052

  1245048

  Press any key to continue



关键词: C语言 链表

评论


相关推荐

技术专区

关闭