新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 牛人業(yè)話 > C語言的那些小秘密之鏈表(二)

C語言的那些小秘密之鏈表(二)

作者: 時間:2015-04-11 來源:網絡 收藏

  從main()函數開始,通過 DList* dlist = dlist_head_create();我們創(chuàng)建了一個頭節(jié)點。值得注意的是,為了更加通用和符合實際需求,我們在此創(chuàng)建的存放的是結構,因為現實中在使用時,絕大部分都是存放結構的,而前一篇文章中我們創(chuàng)建單鏈表時我們存放的是數據,所以這一點讀者是要引起注意的,接下來是一個for循環(huán)語句,在for循環(huán)語句中我們首先使用DStu* stu =(DStu*) malloc(sizeof(DStu));為stu分配了空間,這也是很多讀者的一個易錯點,不分配就使用下面的stu->score = i;語句,從而導致出錯,如果讀者對于指針還不是很了解的話可以看看我前面的文章《的那些小秘密之指針》,在往下看dlist_append(dlist, (void*)stu);語句,從函數名稱我們也可以看出它的功能是在鏈表的末端添加結點的,在函數里面我們使用了一個if判斷語句來看分配的結點是否成功,如果成功繼續(xù)往下執(zhí)行,如果失敗則返回DLIST_RETURN_FAIL。對于第一次分配的節(jié)點我們使用了 thiz->head = node;語句使其變?yōu)轭^結點,在第二次調用dlist_append(dlist, (void*)stu)函數分配結點之后,由于頭結點已經不再為空,那么跳過if(thiz->head == NULL)語句,執(zhí)行以下語句:

本文引用地址:http://m.butianyuan.cn/article/272382.htm

  cursor = thiz->head;

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

  { cursor = cursor->next; }

  其功能為查找末端結點,然后使用 cursor->next = node; node->prev = cursor;語句來將剛剛創(chuàng)建的新結點node作為尾結點。main()函數中的for循環(huán)語句執(zhí)行完之后就輪到了調用dlist_print(dlist, print_int)函數打印我們創(chuàng)建的雙向鏈表保存的數據值了,在這里的時候我們用了前面我博客中提到的函數指針作為參數的使用,如果有對函數指針不熟悉的讀者可以參考我之前寫的一篇博客《的那些小秘密之函數指針》,到此讀者應該都理解了上面的代碼,但是其中有個值得注意的地方,那就是main()函數中使用dlist_append(dlist, (void*)stu);的時候,我們傳遞的是一個無類型的指針,在創(chuàng)建新結點的時候,我們使用了一句node->data =(DStu*)data;進行一個強制轉換,使得鏈表中的數據域指向的就是我們使用DStu* stu =(DStu*) malloc(sizeof(DStu));所創(chuàng)建的空間。創(chuàng)建了空間之后當然要釋放掉,所以接下來我們就添加一個釋放功能模塊。新添加的代碼我們用紅色部分來標記。以便于讀者的閱讀

#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]的指針,所以在創(chuàng)建結點的時候我們使用的node->data =(DStu*)data;語句使得data強制轉換為了DStu結構類型指針,即在結點創(chuàng)建函數中我們僅僅是使數據域的結構指針data指向了stu[i]所分配的存儲空間,和stu[i]指向的是同一個空間,但是在釋放結點時,我們僅僅是釋放掉了存放data指針變量的空間,并沒有釋放掉data所指向的空間,所以我們在main函數中我們最后使用了一個for循環(huán)語句來釋放data所指向的存儲空間。在此也講講之前我給出的以下代碼和我們雙鏈表釋放方式的區(qū)別。

  #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語言 鏈表

評論


相關推薦

技術專區(qū)

關閉