#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct DNode{
int data;//值域
struct DNode * prior;//前驱指针
struct DNode * next;//后继指针
}DLinkNode;
void createListF(DLinkNode * L ,int a[],int n);//创建双链表,采用头插法
void createListR(DLinkNode *L,int a[],int n);//采用尾插法创建双链表
void traverse_list(DLinkNode* pHead);
void destroy_list(DLinkNode* pHead);
int main(){
int a[3] = {1,2,3};
DLinkNode *L = NULL;
createListfF(L,a,3);
traverse_list(L);
destroy_list(L);
return 0;
}
void createListF(DLinkNode * L ,int a[],int n){
L = (DLinkNode *)malloc(sizeof(DLinkNode));//创建头结点
L->next = L->prior = NULL;
for(int i = 0;i < n;i++)
{
DLinkNode * s = (DLinkNode*)malloc(sizeof(DLinkNode));
s->data = a[i];
s->next = L->next;//将新结点插入到头结点之后
if(L->next != NULL)//L存在结点,修改前驱指针
L->next->prior = s;
L->next = s;
s->prior = L;
}
}
void traverse_list(DLinkNode* pHead)
{
DLinkNode * t = pHead->next; // t指向首结点
while (t != NULL)
{
printf("%d ", t->data);
t = t->next;
}
printf("\n");
return;
}
void destroy_list(DLinkNode* pHead){
DLinkNode* pre = pHead,*p = pHead->next;
while (p != NULL)
{
free(pre);
pre = p;
p = pre->next;
}
free(pre);//循环结束时,p为NULL,pre指向尾结点,释放尾结点
}
上面代码,函数crateListR()无返回值,调用遍历函数traverse_list(),并不会打印结点。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct DNode{
int data;//值域
struct DNode * prior;//前驱指针
struct DNode * next;//后继指针
}DLinkNode;
DLinkNode* createListF(DLinkNode * L ,int a[],int n);//创建双链表,采用头插法
DLinkNode* createListR(DLinkNode *L,int a[],int n);//采用尾插法创建双链表
void traverse_list(DLinkNode* pHead);
void destroy_list(DLinkNode* pHead);
int main(){
int a[5] = {1,2,3,8,9};
DLinkNode *L = NULL;
L = createListF(L,a,5);
traverse_list(L);
destroy_list(L);
return 0;
}
DLinkNode* createListF(DLinkNode * L ,int a[],int n){
L = (DLinkNode *)malloc(sizeof(DLinkNode));//创建头结点
L->next = L->prior = NULL;
for(int i = 0;i < n;i++)
{
DLinkNode * s = (DLinkNode*)malloc(sizeof(DLinkNode));
s->data = a[i];
s->next = L->next;//将新结点插入到头结点之后
if(L->next != NULL)//L存在结点,修改前驱指针
L->next->prior = s;
L->next = s;
s->prior = L;
}
return L;
}
void traverse_list(DLinkNode* pHead)
{
DLinkNode * t = pHead->next; // t指向首结点
while (t != NULL)
{
printf("%d ", t->data);
t = t->next;
}
printf("\n");
return;
}
void destroy_list(DLinkNode* pHead){
DLinkNode* pre = pHead;
DLinkNode* p = pHead->next;
while (p != NULL)
{
free(pre);
pre = p;
p = pre->next;
}
free(pre);//循环结束时,p为NULL,pre指向尾结点,释放尾结点
}
把函数crateListR()返回值改为返回DLinkNode*后(并赋给L),调用遍历函数traverse_list(),才能打印出结点。
实参L传给形参L,函数调用后形参L会被释放,但malloc()开辟的内存空间在函数调用后并不会被释放,为什么会出现这种情况呢?
想明白了,这里犯了一个低级的错误。
形参L,经过malloc()调用分配后了一片新的堆空间,malloc()返回这片空间的基地址,那么形参L中就不再是实参中的地址了。形参L在函数调用后也确实被释放了,但通过return,把形参L地址返回(即基地址),赋值给实参L,也就能找到这些内存了。
更简单的做法是使用引用变量(可惜C语言暂不支持)。
更复杂的做法是使用二级指针,通过解除引用运算符可以达到同样效果。