双向链表:在单向链表的每个结点中,再设置一个指向其前驱结点的指针域(即牺牲部分空间,添加了一个前驱结点的指针域)
1. 双向链表的定义:
#ifndef _DOULINK_H_
#define _DOULINK_H_typedef struct stu
{int id;char name[32];int score;
}DATA_TYPE;typedef struct node
{DATA_TYPE data;struct node *pnext;struct node *ppre;
}DOU_NODE;typedef struct list
{DOU_NODE *phead;int curlen;
}DOU_LIST;typedef void (*PFUN_T)(DOU_NODE *);#endif
2. 双向链表句柄的创建:
DOU_LIST *Create_Dou_List(void)
{DOU_LIST *plist = malloc(sizeof(DOU_LIST));if(plist == NULL){perror("fail to malloc");return NULL;}plist->phead = NULL;plist->curlen = 0;return plist;
}
3. 双向链表结点的创建:
DOU_NODE *Creat_Node(DATA_TYPE data)
{DOU_NODE *pnode = malloc(sizeof(DOU_NODE));if(pnode == NULL){perror("fail to malloc");return NULL;}pnode->data = data;pnode->pnext = NULL;pnode->ppre = NULL;return pnode;
}
4. 双向链表的遍历:
void Dou_List_For_Each(DOU_LIST *plist, void (*pfun)(DOU_NODE *))
{DOU_NODE *ptmp = plist->phead;while(ptmp != NULL){pfun(ptmp);ptmp = ptmp->pnext;}#if 0 //反向遍历while(ptmp->pnext != NULL){ptmp = ptmp->pnext;}while(ptmp != NULL){printf("id = %d name = %s\t score = %02d\n", ptmp->data.id, ptmp->data.name, ptmp->data.score);ptmp = ptmp->ppre;}
#endifreturn;
}
5. 双向链表头插法:
int Is_Empty_Link(DOU_LIST *plist)
{return plist->phead == NULL;
}int Push_Head_Dou_Link(DOU_LIST *plist, DOU_NODE *pnode)
{if(plist == NULL || pnode == NULL){return -1;}if(Is_Empty_Link(plist)){plist->phead = pnode;}else{pnode->pnext = plist->phead;pnode->pnext->ppre = pnode;plist->phead = pnode;}plist->curlen++;return 0;
}
6. 双向链表尾插法:
int Push_Tail_Dou_Link(DOU_LIST *plist, DOU_NODE *pnode)
{if(plist == NULL || pnode == NULL){return -1;}if(Is_Empty_Link(plist)){plist->phead = pnode;}else{DOU_NODE *ptmp = plist->phead;while(ptmp->pnext != NULL){ptmp = ptmp->pnext;}ptmp->pnext = pnode;pnode->ppre = ptmp;}plist->curlen++;return 0;
}
7. 双向链表头删法:
int Pop_Head_Dou_Link(DOU_LIST *plist)
{if(Is_Empty_Link(plist)){return 0;}if(plist->phead->pnext == NULL){free(plist->phead);plist->phead = NULL;}else{DOU_NODE *ptmp = plist->phead;plist->phead = ptmp->pnext;ptmp->pnext->ppre = NULL;free(ptmp);}plist->curlen--;return 0;
}
8. 双向链表尾删法:
int Pop_Tail_Dou_Link(DOU_LIST *plist)
{if(Is_Empty_Link(plist)){return 0;}if(plist->phead->pnext == NULL){free(plist->phead);plist->phead = NULL;}else{DOU_NODE *ptmp = plist->phead;while(ptmp->pnext != NULL){ptmp = ptmp->pnext;}ptmp->ppre->pnext = NULL;free(ptmp);}plist->curlen--;return 0;
}
9. 双向链表找到数据的结点:
DOU_NODE *Find_Node(DOU_LIST *plist, DATA_TYPE data)
{DOU_NODE *ptmp = plist->phead;while(ptmp != NULL){if(!memcmp(&ptmp->data, &data, sizeof(data))){return ptmp;}ptmp = ptmp->pnext;}return NULL;
}
10. 双向链表替换数据:
int Replace_Node(DOU_LIST *plist, DATA_TYPE olddata, DATA_TYPE newdata)
{DOU_NODE *ptmp = plist->phead;while(ptmp != NULL){if(!memcmp(&ptmp->data, &olddata, sizeof(olddata))){ptmp->data = newdata;return 0;}ptmp = ptmp->pnext;}return -1;
}
11. 双向链表的销毁:
void Destroy_Dou_Link(DOU_LIST *plist)
{while(plist->phead != NULL){Pop_Head_Dou_Link(plist);}free(plist);return;
}
12. 双向链表删除某个结点:
int Delete_Data(DOU_LIST *plist, void *data, int (*pfun)(DOU_NODE *, void *))
{if(Is_Empty_Link(plist)){return 0;}DOU_NODE *pfree = plist->phead;while(pfree != NULL){if(pfun(pfree, data)){if(pfree == plist->phead){plist->phead = pfree->pnext;pfree->pnext->ppre = NULL;free(pfree);}else if(pfree->pnext == NULL){pfree->ppre->pnext = NULL;free(pfree);}else{pfree->ppre->pnext = pfree->pnext;pfree->pnext->ppre = pfree->ppre;free(pfree);}plist->curlen--;return 0;}else{pfree = pfree->pnext;}}return -1;
}
13. 双向链表逆序:
int Reverse_Dou_Link(DOU_LIST *plist)
{if(Is_Empty_Link(plist)){return 0;}DOU_NODE *ptmp = plist->phead->pnext;DOU_NODE *pinsert = NULL;plist->phead->pnext = NULL;while(ptmp != NULL){pinsert = ptmp;ptmp = ptmp->pnext;pinsert->ppre = NULL;pinsert->pnext = plist->phead;plist->phead->ppre = pinsert;plist->phead = pinsert;}return 0;
}