您的位置:首页 > 编程语言 > C语言/C++

C语言实现双链表

2016-03-21 09:22 417 查看
双链表一定要注意,前驱指针,Erase的时候,要判断next是否为NULL,要不然不能使用前驱指针

结点定义如下:

typedef int DataType;
typedef struct ListNode
{
DataType data;
ListNode* prev;
ListNode* next;
};


实现了的函数的声明如下:

ListNode* _BuyNode(DataType x);
void PrintNode(ListNode* pHead);
void PushBack(ListNode*& pHead, DataType x);
void PopBack(ListNode*& pHead);
void PushFront(ListNode*& pHead, DataType x);
ListNode* Find(ListNode* pHead, DataType x);
void Insert(ListNode*& pos, DataType x);//要分两种情况,要不然pos是尾的话,next->prev将崩溃
void Erase(ListNode*& pHead, ListNode* pos);//删除的时候,分条件:1.为头节点2.不为头节点


具体实现如下:

ListNode* _BuyNode(DataType x)
{
ListNode* tmp = (ListNode*)malloc(sizeof(ListNode));
tmp->data = x;
tmp->next = NULL;
tmp->prev = NULL;
return tmp;
}

void PrintNode(ListNode* pHead)
{
ListNode* cur = pHead;
while (cur != NULL)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}

void PushBack(ListNode*& pHead,DataType x)
{
if (pHead == NULL)
{
pHead = _BuyNode(x);
return;
}
else
{
ListNode* cur = pHead;
while (cur->next)
{
cur = cur->next;
}
ListNode* tmp = _BuyNode(x);
cur->next = tmp;
tmp->prev = cur;
}
}

void PopBack(ListNode*& pHead)
{
if (pHead == NULL)
{
return;
}
else if (pHead->next == NULL)//上面的判断条件,已经保证这里不为pHead!=NULL
{
free(pHead);
pHead = NULL;
}
else//看似第二个判断条件和第三个判断条件可以何为一个
{
ListNode* tmp = pHead->next;
free(pHead);
pHead = tmp;
tmp->prev = NULL;//但是这里会出问题
}
}

void PushFront(ListNode*& pHead, DataType x)
{
if (pHead == NULL)
{
pHead = _BuyNode(x);
return;
}
else
{
ListNode* tmp = pHead;
pHead = _BuyNode(x);
pHead->next = tmp;
tmp->prev = pHead;
}
}

void PopFront(ListNode*& pHead)
{
if (pHead==NULL)
{
return;
}
else if (pHead->next == NULL)
{
free(pHead);
pHead = NULL;
}
else
{
ListNode* tmp = pHead->next;
free(pHead);
pHead = tmp;
pHead->prev = NULL;
}
}

ListNode* Find(ListNode* pHead, DataType x)
{
ListNode* cur = pHead;
while (cur)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}

void Insert(ListNode*& pos, DataType x)//要分两种情况,要不然pos是尾的话,next->prev将崩溃
{
assert(pos);
ListNode* tmp = _BuyNode(x);
if (pos->next == NULL)
{
pos->next = tmp;
tmp->prev = NULL;
}
else
{
ListNode* next = pos->next;
pos->next = tmp;
tmp->prev = pos;
tmp->next = next;
next->prev = tmp;
}
}

void Erase(ListNode*& pHead,ListNode* pos)//删除的时候,分条件:1.为头节点2.不为头节点
{
assert(pHead);
assert(pos);
if (pHead == pos)
{
PopFront(pHead);
}
else
{
ListNode* cur = pHead;
ListNode* prev = pHead;
while (cur)
{
prev = cur;
cur = cur->next;
if (cur == pos)
{
ListNode* next = cur->next;//因为pos不为NULL所以保证cur不为NULL
if (next == NULL)//双链表删除的时候,一定要判断是不是为尾节点,尾节点一定要注意前驱指针
{
PopBack(pHead);
}
else
{
prev->next = next;
next->prev = prev;
free(cur);
return;
}
}
}
}
}


测试用例如下:

因为Erase比较特殊,就只写这个的测试用例

void Test()
{
SListNode* list1 = NULL;
PushBack(&list1, 1);
PushBack(&list1, 2);
PushBack(&list1, 3);
PushBack(&list1, 4);
PushBack(&list1, 5);
PrintSlist(list1);
Erase(list1, list1->next);
PrintSlist(list1);
Erase(list1, list1->next);
PrintSlist(list1);
Erase(list1, list1->next);
PrintSlist(list1);
Erase(list1, list1->next);
PrintSlist(list1);
Erase(list1, list1);
PrintSlist(list1);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  双链表