上一篇讲到了双链表的基本操作(头删头插尾删尾插)
这一篇讲讲双向链表的其他操作
一.查找一个数据
DLinkNode* DLinkListFind(DLinkNode* head, DLinkType to_find)
{
if (head == NULL)
return NULL;
if (head->next == head)
return NULL;
DLinkNode* cur = head->next;
for(; cur->next != head;cur = cur->next)
{
if(cur->data == to_find)
return cur;
}
return NULL;
}
思路:遍历,找到含有这个数据的节点,返回该节点的地址
1.指针的合法性判断
2.空链表判断
3.遍历
二.指定位置之前插入一个节点
void DLinkListInsert(DLinkNode* pos, DLinkType value)
{
if (pos == NULL)
return;
DLinkNode* insert = CreatDLinkNode(value);
DLinkNode* insert_pre = pos->prev;
insert->next = pos;
pos->prev = insert;
insert_pre->next = insert;
insert->prev = insert_pre;
return;
}
思路:修改两组指针的指向
1.指针合法性判断
2.创建一个节点
3.前插
三.指定位置之后插入一个节点
void DLinkListInsertAfter(DLinkNode* pos, DLinkType value)
{
if (pos == NULL)
return;
DLinkNode* insert = CreatDLinkNode(value);
DLinkNode* insert_next = pos->next;
insert->next = insert_next;
insert_next->prev = insert;
pos->next = insert;
insert->prev = pos;
return;
}
思路:
1.指针合法性判断
2.创建一个节点
3.后插
四.删除指定位置的元素
void DLinkListErase(DLinkNode* head,DLinkNode* pos)//删除指定位置的元素
{
if (head == NULL || pos == NULL)
return;
if (head->next == head)
return;
DLinkNode* cur = head->next;
for(; cur != head; cur = cur->next)
{
if (cur == pos)
{
DLinkNode* to_delete = cur;
DLinkNode* to_delete_prev = cur->prev;
DLinkNode* to_delete_next = to_delete->next;
to_delete_prev->next = to_delete_next;
to_delete_next->prev =to_delete_prev;
DestroyNode(to_delete);
break;
}
}
return;
}
思路:遍历
1.两个指针的合法性判断
2.空链表判断
3.遍历找该位置,找到则删除(修改一组指针)
五.删除指定值元素(链表中若有多个相同元素,删除第一个)
void DLinkListRemove(DLinkNode* head,DLinkType value) //删除指定值的元素
{
if (head == NULL)
return;
if (head->next == head)
return;
DLinkNode* cur = head->next;
for(; cur != head; cur = cur->next)
{
if (cur->data == value)
{
DLinkNode* to_delete = cur;
DLinkNode* to_delete_prev = cur->prev;
DLinkNode* to_delete_next = to_delete->next;
to_delete_prev->next = to_delete_next;
to_delete_next->prev =to_delete_prev;
DestroyNode(to_delete);
break;
}
}
return;
}
思路:遍历
1.指针合法性判断
2.空链表判断
3.遍历查找值,找到则删除节点(修改一组指针)
六.删除指定值元素(链表中若有多个相同元素,删除所有)
void DLinkListRemoveAll(DLinkNode* head,DLinkType value)//删除所有相同值得元素
{
if (head == NULL)
return;
if (head->next == head)
return;
DLinkNode* cur = head->next;
for(; cur != head; cur = cur->next)
{
if (cur->data == value)
{
DLinkNode* to_delete = cur;
DLinkNode* to_delete_prev = cur->prev;
DLinkNode* to_delete_next = to_delete->next;
to_delete_prev->next = to_delete_next;
to_delete_next->prev =to_delete_prev;
DestroyNode(to_delete);
}
}
return;
}
思路同上一个一样,只不过找到一个相同元素,在循环内不要break跳出循环就行了。
七.求链表长度
int DLinkListSize(DLinkNode* head) //链表长度
{
if ( head == NULL )
return -1;
if ( head == head->next )
return 0;
size_t count = 0;
DLinkNode* cur = head->next;
while (cur != head)
{
count++;
cur = cur->next;
}
return count;
}
思路:遍历+计数器
1.指针的合法性判断
2.空链表判断
3.定义一个计数器,遍历链表,返回计数器的值
所有关于双向链表的测试代码如下:
void TestDLinkListPushBack()
{
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListPrintChar(head, "尾插打印双向链表");
}
void TestDLinkListPopBack()
{
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListPopBack(head);
DLinkListPrintChar(head, "尾删打印双向链表");
}
void TestDLinkListPushFront()
{
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListPushFront(head,'d');
DLinkListPrintChar(head, "头插 d");
}
void TestDLinkListPopFront()
{
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListPopFront(head);
DLinkListPrintChar(head, "头删");
}
void TestDLinkListErase()
{
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkNode* find = DLinkListFind(head, 'b');
DLinkListErase(head, find);
DLinkListPrintChar(head, "找到b,并删掉");
}
void TestDLinkListRemove()
{
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListPushBack(head,'a');
DLinkListRemove(head, 'a'); //删除指定值的元素
DLinkListPrintChar(head, "删掉元素a");
}
void TestDLinkListRemoveAll()
{
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListPushBack(head,'a');
DLinkListRemoveAll(head, 'a'); //删除指定值的元素
DLinkListPrintChar(head, "删掉所有元素a");
}
void TestDLinkListDestory()
{
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListDestory(&head);
DLinkListPrintChar(head, "双链表销毁");
}
void TestDLinkListSize()
{
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
int ret = DLinkListSize(head); //链表长度
DLinkListPrintChar(head, "双链表");
printf("长度为:%d\n",ret);
}
int main()
{
TestDLinkListPushBack();
TestDLinkListPopBack();
TestDLinkListPushFront();
TestDLinkListPopFront();
TestDLinkListErase();
TestDLinkListRemove();
TestDLinkListRemoveAll();
TestDLinkListDestory();
TestDLinkListSize();
return 0;
}
测试结果: