双向链表的概念:
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
双向链表的分类:
- 不带头双向链表
- 带头双向链表
示意图:
不带头双向链表:
详细代码请看:
https://blog.csdn.net/yanhuan136675/article/details/82766441
带头双向链表:(非循环)
dlist.h
#pragma once
typedef struct DNode
{
int data;//数据域
struct DNode *next;//后继指针
struct DNode *prio;//前驱指针
}DNode,*DList;
//初始化双向链表
void InitDList(DList plist);
//头插
bool Insert_head(DList plist,int val);
//尾插
bool Insert_tail(DList plist,int val);
//查找
DNode *Search(DList plist,int key);
//删除
bool Delete(DList plist,int key);
//获取长度(数据结点的个数)
int GetLength(DList plist);
//判空
bool IsEmpty(DList plist);
//清空
void Clear(DList plist);
//摧毁
void Destroy(DList plist);
//打印
void Show(DList plist);
//逆置
void Reverse(DList plist);
dlist.cpp:
//初始化双向链表
void InitDList(DList plist)
{
assert(plist != NULL);
if(plist == NULL)
{
return ;
}
plist->next = NULL;
plist->prio = NULL;
}
//头插
bool Insert_head(DList plist,int val)
{
assert(plist != NULL);
if(plist == NULL)
{
return false;
}
DNode *p = (DNode *)malloc(sizeof(DNode));
p->data = val;
p->next = plist->next;
plist->next = p;
p->prio = plist;
if(p->next != NULL)
{
p->next->prio = p;
}
return true;
}
//尾插
bool Insert_tail(DList plist,int val)
{
assert(plist != NULL);
if(plist == NULL)
{
return false;
}
DNode *p = (DNode *)malloc(sizeof(DNode));
p->data = val;
DNode *q;
for(q = plist;q->next != NULL;q = q->next);//找尾巴
//将p插在q的后面
p->next = q->next;
q->next = p;
p->prio = q;
return true;
}
//查找
DNode *Search(DList plist,int key)
{
assert(plist != NULL);
if(plist == NULL)
{
return false;
}
for(DNode *p = plist->next;p != NULL;p = p->next)
{
if(p->data == key)
{
return p;
}
}
return NULL;
}
//删除
bool Delete(DList plist,int key)
{
assert(plist != NULL);
if(plist == NULL)
{
return false;
}
DNode *p = Search(plist,key);
if(p == NULL)
{
return false;
}
p->prio->next = p->next;
if(p->next != NULL)
{
p->next->prio = p->prio;
}
free(p);
return true;
}
//获取长度(数据结点的个数)
int GetLength(DList plist)
{
int count = 0;
for(DNode *p = plist->next;p != NULL;p = p->next)
{
count++;
}
return count;
}
//判空
bool IsEmpty(DList plist)
{
return plist->next == NULL;
}
//清空
void Clear(DList plist)
{
Destroy(plist);
}
//摧毁
void Destroy(DList plist)
{
DNode *p;
while(plist->next != NULL)
{
p = plist->next;
plist->next = p->next;
free(p);
}
}
//打印
void Show(DList plist)
{
for(DNode *p = plist->next;p != NULL;p = p->next)
{
printf("%d ",p->data);
}
printf("\n");
}
//逆置
void Reverse(DList plist)
{
DNode *p = plist->next;
DNode *q;
int tmp;
for(q = plist;q->next != NULL;q = q->next);//找尾巴
for(int i = 0;i < GetLength(plist)/2;i++)
{
tmp = p->data;
p->data = q->data;
q->data = tmp;
p = p->next;
q = q->prio;
}
}
主函数:
#include<stdio.h>
#include<vld.h>//测试内存泄漏的头文件
#include"dlist.h"
int main()
{
DNode head1;
DNode head2;
InitDList(&head1);
InitDList(&head2);
for(int i = 0;i < 10;i++)
{
Insert_head(&head1,i);
Insert_tail(&head2,i);
}
Show(&head1);
Show(&head2);
printf("%d\n",Delete(&head1,3));
printf("%d\n",GetLength(&head2));
Destroy(&head1);
Destroy(&head1);
Reverse(&head2);
Show(&head2);
return 0;
}