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