目录
双向链表操作
头文件定义
双向链表的初始化
双向链表的插入
双线链表求链表长度
双向链表的判空
双向链表的遍历
双向链表的查找(通过位置求值)
双向链表的检索(通过值求位置)
双向链表的删除
双向链表的重置
双向链表的销毁
测试文件
像双向链表的求长,判空,遍历,查找,检索,之类的操作都和单链表一样的。不过我还是在了文中。
#ifndef _DOUBLELINKLIST_H_
#define _DOUBLELINKLIST_H_
#include
#include
#define SUCCESS 10000
#define FAILURE 10001
#define TRUE 10002
#define FALSE 10003
typedef int ElemType;
struct node
{
ElemType data;
struct node *next;
struct node *prior;
};
typedef struct node Node;
int LinkInit( Node **ppHeadNode);
int LinkInsert( Node *pHeadNode, int position, ElemType e);
int LinkLength( Node *pHeadNode);
int LinkEmpty( Node *pHeadNode);
int LinkTraverse( Node *pHeadNode, void (*visit)(ElemType));
int GetElem( Node *pHeadNode, int position, ElemType *e);
int LocateElem( Node *pHeadNode, ElemType e, int compare(ElemType, ElemType));
int LinkDelete( Node *pHeadNode, int position, ElemType *e);
int LinkClear( Node *pHeadNode);
int LinkDestory( Node **ppHeadNode);
int ReverseLink( Node *pHeadNode);
#endif
//链表初始化
int LinkInit(Node **ppHeadNode)
{
if( NULL == ppHeadNode)//入参判断
{
return FAILURE;
}
(*ppHeadNode) = (Node *) malloc (sizeof(Node));//为(*ppHeadNode)分配节点空间
if( NULL == (*ppHeadNode))
{
return FAILURE;
}
(*ppHeadNode)->next = NULL;
(*ppHeadNode)->prior = NULL;
return SUCCESS;
}
双链表的插入操作的基本思路是这样的。
1.定位。确定插入的位置。代码中的count就是用来定位的,pNode则是保存定位的到的节点
2.分配空间。定义一个新节点pNewNode 并给他分配空间。
3.传值。把要插入的数据传给刚刚已分配好空间的新节点。
4.执行插入操作。插入操作见下图。
//双向链表插入操作,position 是要插入的位置, e 是要插入的数据
int LinkInsert(Node *pHeadNode, int position, ElemType e)
{
if( NULL == pHeadNode || position < 1)//入参判断,链表要存在, position 最小为1
{
return FAILURE;
}
if( position > LinkLength(pHeadNode) + 1)//入参判断,确保 position 有效
{
return FAILURE;
}
Node *pNewNode = NULL; //pNewNode 为要插入的新节点
Node *pNode = pHeadNode; //pNode 遍历链表,最终指向要插入位置的前一个节点
int count = 0; //count 用来确定 pNode 指向的位置
while( count < position - 1)
{
pNode = pNode->next;
count++;
}
if( count != position - 1) //再次确认位置
{
return FAILURE;
}
pNewNode = (Node *) malloc (sizeof(Node));//为 pNewNode 分配节点空间
pNewNode->data = e; //把要插入的数据传给新节点
//插入操作
pNewNode->prior = pNode; //先让pNewNode附着在pNode之后,使pNewNode链接上链表
pNewNode->next = pNode->next;
pNode->next = pNewNode; //再断开多余的链接
if( pNode->next != NULL) //如果pNode不是尾节点
{
pNode->next->prior = pNewNode;
}
return SUCCESS;
}
//求链表长度
int LinkLength(Node *pHeadNode)
{
if( NULL == pHeadNode) //入参判断
{
return FAILURE;
}
Node *pNode = pHeadNode; //pNode 遍历链表
int length = 0; //length 记录链表长度
while( pNode->next != NULL)
{
pNode = pNode->next;
length++;
}
return length;
}
//判断链表是否为空
int LinkEmpty(Node *pHeadNode)
{
return pHeadNode->next == NULL ? TRUE : FALSE;
}
//链表的遍历操作
int LinkTraverse(Node *pHeadNode, void (*visit)(ElemType))
{
if( NULL == pHeadNode) //入参判断
{
return FAILURE;
}
Node *pNode = pHeadNode; //pNode 遍历链表
while( pNode->next != NULL)
{
pNode = pNode->next;
(*visit)(pNode->data);
}
return SUCCESS;
}
//获取某个位置上的数据
int GetElem(Node *pHeadNode, int position, ElemType *e)
{
if( NULL == pHeadNode || position < 1) //入参判断
{
return FAILURE;
}
if( position > LinkLength(pHeadNode) )
{
return FAILURE;
}
Node *pNode = pHeadNode; //pNode 遍历链表
int count;
while( count < position) //让pNode指向position位置的节点
{
pNode = pNode->next;
count++;
}
if( count != position) //再次确认位置
{
return FAILURE;
}
*e = pNode->data; //传值
return SUCCESS;
}
//函数返回链表中第一个与元素e满足关系compare()的位置
int LocateElem(Node *pHeadNode, ElemType e, int compare(ElemType, ElemType))
{
if( NULL == pHeadNode) //入参判断
{
return FAILURE;
}
Node *pNode = pHeadNode->next; //pNode 遍历链表
int count = 0; //count 记录位置
while( pNode != NULL)
{
if( TRUE == compare(pNode->data, e)) //如果pNode->data与e满足关系compare
{
return count + 1; //返回位置
}
pNode = pNode->next;
count++;
}
return FAILURE;
}
//链表的删除操作,position 为要删除的位置,*e 保存被删除的数据
int LinkDelete(Node *pHeadNode, int position, ElemType *e)
{
if( NULL == pHeadNode || position < 1) //入参判断
{
return FAILURE;
}
if( position > LinkLength(pHeadNode))
{
return FAILURE;
}
Node *pNode = pHeadNode; //pNode 遍历链表,最终指向要删除的前节点
int count = 0; //count 确保位置
while( count < position )
{
pNode = pNode->next;
count++;
}
if( count != position ) //再次确认位置
{
return FAILURE;
}
//删除操作
*e = pNode->data; //记录将被删除节点上的数据
pNode->prior->next = pNode->next; //剥离要删除的节点
pNode->next->prior = pNode->prior;
free(pNode); //释放已经被剥离的节点的空间
pNode = NULL;
return SUCCESS;
}
//清空链表
int LinkClear(Node *pHeadNode)
{
if( NULL == pHeadNode) //入参判断
{
return FAILURE;
}
Node *pNode = pHeadNode->next; //pNode 指向被清空的节点
while( NULL != pNode->next) //循环销毁节点
{
pHeadNode->next = pNode->next; //剥离pNode
pNode->next->prior = pHeadNode;
free(pNode);
pNode = pNode->next;
}
if( NULL != pNode) //清空最后一个节点
{
free(pNode);
pNode = NULL;
pHeadNode->next = NULL; //头结点初始化
}
return SUCCESS;
}
//销毁链表
int LinkDestory(Node **ppHeadNode)
{
if( NULL == ppHeadNode ) //入参判断
{
return FAILURE;
}
Node *pNode = NULL; //pNode 指向将被销毁的节点的下一个节点
while( NULL != (*ppHeadNode) )
{
pNode = (*ppHeadNode)->next; //将下个要被销毁的节点的地址传给pNode
free(*ppHeadNode); //销毁 *ppHeadNode
(*ppHeadNode) = pNode; //把pNode里的地址传给*ppHeadNode
}
if( NULL == (*ppHeadNode)) //确认节点都被销毁
{
return SUCCESS;
}
return FAILURE;
}
#include
#include "doublelinklist.h"
#include
void print(ElemType e)
{
printf("%d ", e);
}
int eq(ElemType L_e, ElemType e)
{
return L_e == e ? TRUE : FALSE;
}
int gt(ElemType L_e, ElemType e)
{
return L_e > e ? TRUE : FALSE;
}
int lt(ElemType L_e, ElemType e)
{
return L_e < e ? TRUE : FALSE;
}
int main()
{
Node *pHeadNode;
int ret, position, i;
ElemType e;
srand(time(NULL));
ret = LinkInit(&pHeadNode); //链表初始化
if( FAILURE == ret)
{
printf("Init failure.\n");
}
else if( SUCCESS == ret)
{
printf("Init success.\n");
}
for( i = 0; i < 10; i++)
{
e = rand() % 20;
ret = LinkInsert(pHeadNode, i+1, e); //链表插入
if( FAILURE == ret)
{
printf("Insert failure.\n");
}
else if( SUCCESS == ret)
{
printf("Insert success.\n");
}
}
ret = LinkLength(pHeadNode); //链表求长
if( FAILURE == ret)
{
printf("Length failure.\n");
}
else
{
printf("Length = %d\n", ret);
}
ret = LinkEmpty(pHeadNode); //链表判空
if( FALSE == ret)
{
printf("Not Empty.\n");
}
else if( TRUE == ret)
{
printf("Empty.\n");
}
ret = LinkTraverse(pHeadNode, print); //链表遍历
if( FAILURE == ret)
{
printf("\nTraverse failure.\n");
}
else if( SUCCESS == ret)
{
printf("\nTraverse success.\n");
}
position = 4;
ret = GetElem(pHeadNode, position, &e); //获取某位置上的数据
if( FAILURE == ret)
{
printf("Get %dth element failure.\n", position);
}
else if( SUCCESS == ret)
{
printf("%dth element is %d.\n", position, e);
}
e = 10;
ret = LocateElem(pHeadNode, e, eq); //返回10在链表第一次出现的位置
if( FAILURE == ret)
{
printf("Locate element %d failure.\n", e);
}
else
{
printf("%d is %dth element.\n", e, ret);
}
position = 3;
ret = LinkDelete(pHeadNode, position, &e); //链表删除
if( FAILURE == ret)
{
printf("Delete failure.\n");
}
else if( SUCCESS == ret)
{
printf("Delete %dth element %d success.\n", position, e);
}
ret = LinkTraverse(pHeadNode, print); //链表遍历
if( FAILURE == ret)
{
printf("\nTraverse failure.\n");
}
else if( SUCCESS == ret)
{
printf("\nTraverse success.\n");
}
ret = LinkClear(pHeadNode); //链表重置
if( FAILURE == ret)
{
printf("Clear failure.\n");
}
else if( SUCCESS == ret)
{
printf("Clear success.\n");
}
ret = LinkLength(pHeadNode); //链表求长
if( FAILURE == ret)
{
printf("Length failure.\n");
}
else
{
printf("Length = %d\n", ret);
}
ret = LinkDestory(&pHeadNode); //链表销毁
if( FAILURE == ret)
{
printf("Destory failure.\n");
}
else if( SUCCESS == ret)
{
printf("Destory success.\n");
}
for( i = 0; i < 4; i++)
{
e = rand() % 20;
ret = LinkInsert(pHeadNode, i+1, e); //链表插入
if( FAILURE == ret)
{
printf("Insert failure.\n");
}
else if( SUCCESS == ret)
{
printf("Insert success.\n");
}
}
return 0;
}