目录
双向链表
双向链表是一种链表结构。
一、结构特点
-
每个节点包含两个指针,分别指向直接前驱节点和直接后继节点。这使得在双向链表中可以双向遍历,既可以向前也可以向后查找节点。
-
相比单向链表,双向链表在某些操作上更加灵活,比如在删除节点时,可以快速找到前驱节点进行调整,而单向链表需要从头开始遍历才能找到前驱节点。
二、操作优势
-
插入操作:可以快速确定插入位置的前后节点,进行指针调整,实现高效的插入操作。
-
删除操作:由于能够直接访问前驱节点,删除操作也更加方便快捷。
三、应用场景
-
需要频繁进行前后遍历的场景,如文本编辑器中对字符的双向移动和操作。
-
对数据的插入和删除操作较多,且要求高效的系统中。
1.创建链表
cs
LinkList *CreateLinkList()
{
LinkList*ll = (LinkList*)malloc(sizeof(LinkList));
if(NULL == ll)
{
perror("CreateLinkList malloc");
return NULL;
}
ll->head = NULL;
ll->clen = 0;
return ll;
}
2.头插数据
cs
int InsertHeadLinkList(LinkList *list, DATATYPE *data)
{
LinkNode* newnode = (LinkNode*)malloc(sizeof(LinkNode));
if(NULL == newnode)
{
perror("InsertHeadLinkList malloc");
return 1;
}
memcpy(&newnode->data,data,sizeof(DATATYPE));
newnode->next = NULL;
newnode->prev = NULL;
if(IsEmptyLinkList(list))
{
list->head = newnode;
}
else
{
newnode->next = list->head;
list->head->prev = newnode;
list->head = newnode;
}
list->clen++;
return 0;
}
3.打印数据
cs
int ShowLinkList(LinkList *list ,DIRECT dir)
{
int i=0;
int len =GetSizeLinkList(list);
LinkNode* tmp = list->head;
if(DIR_FORWARD == dir)
{
for(i = 0 ;i<len;i++)
{
printf("name:%s age:%d score:%d\n",tmp->data.name,tmp->data.age,tmp->data.score);
tmp=tmp->next;
}
}
else
{
while(tmp->next)
{
tmp=tmp->next;
}
while(tmp)
{
printf("name:%s age:%d score:%d\n",tmp->data.name,tmp->data.age,tmp->data.score);
tmp=tmp->prev;
}
}
return 0;
}
4.查找数据
cs
LinkNode *FindLinkList(LinkList *list, char *name)
{
int len = GetSizeLinkList(list);
int i = 0 ;
LinkNode*tmp = list->head;
for(i = 0 ;i<len;i++)
{
if(0==strcmp(tmp->data.name,name))
{
return tmp;
}
tmp=tmp->next;
}
return NULL;
}
5.删除数据
cs
int DeleteLinkList(LinkList *list, char *name)
{
LinkNode*tmp = FindLinkList(list,name);
if(NULL == tmp)
{
return 1;
}
if(tmp->next)
{
tmp->next->prev=tmp->prev;
}
if(tmp->prev)
{
tmp->prev->next = tmp->next;
}
else
{
list->head = tmp->next;
}
free(tmp);
list->clen--;
return 0;
}
6.更改数据
cs
int ModifyLinkList(LinkList *list, char *name, DATATYPE *data)
{
LinkNode* tmp = FindLinkList(list,name);
if(NULL == tmp)
{
return 1;
}
memcpy(&tmp->data,data,sizeof(DATATYPE));
return 0;
}
7.清空数据
cs
int DestroyLinkList(LinkList *list)
{
LinkNode* tmp = list->head;
while(tmp)
{
list->head= list->head->next;
free(tmp);
tmp = list->head;
}
free(list);
return 0;
}
8.尾插数据
cs
int InsertTailLinkList(LinkList *list, DATATYPE *data)
{
if(IsEmptyLinkList(list))
{
return InsertHeadLinkList(list,data);
}
else
{
LinkNode* newnode = (LinkNode*)malloc(sizeof(LinkNode));
if(NULL == newnode)
{
perror("inster tail malloc");
return 1;
}
// newnode init
memcpy(&newnode->data,data,sizeof(DATATYPE));
newnode->next = NULL;
newnode->prev=NULL;
LinkNode*tmp = list->head;
while(tmp->next)
{
tmp = tmp->next;
}
newnode->prev = tmp;
tmp->next = newnode;
}
list->clen++;
return 0;
}
9.按位插入
cs
int InsertPosLinkList(LinkList *list, DATATYPE *data, int pos) {
int len = GetSizeLinkList(list);
if (pos < 0 || pos > len) {
return 1;
}
if (0 == pos) {
return InsertHeadLinkList(list, data);
} else if (len == pos) {
return InsertTailLinkList(list, data);
} else {
LinkNode *tmp = list->head;
int i = 0;
for (i = 0; i < pos - 1; i++) {
tmp = tmp->next;
}
LinkNode *newnode = (LinkNode *)malloc(sizeof(LinkNode));
if (NULL == newnode) {
perror("insert pos malloc");
return 1;
}
memcpy(&newnode->data, data, sizeof(DATATYPE));
newnode->next = NULL;
newnode->prev = NULL;
newnode->prev = tmp;
newnode->next = tmp->next;
tmp->next->prev = newnode;
tmp->next = newnode;
}
list->clen++;
return 0;
}
10.获取长度
cs
int GetSizeLinkList(LinkList*list)
{
return list->clen;
}
11.是否为空
cs
int IsEmptyLinkList(LinkList*list)
{
return 0 == list->clen;
}