文章目录
2.双向链表
2.1双向链表的创建
//定义一个双向链表
typedef struct LNode
{
int data;
struct LNode* prior;
struct LNode* next;
}DListNode, * DLinkList;
2.2初始化双向链表
//初始化双向链表
void InitLinkList(DLinkList* L)
{
*L = (DLinkList)malloc(sizeof(DListNode));//为头结点分配空间
if (*L == NULL)
{
printf("开辟内存空间失败,初始化头结点失败\n");
return -1;
}
(*L)->next = NULL;
(*L)->prior = NULL;
printf("双向链表初始化成功....\n");
}
2.3打印双向链表
//打印双向单链表
void printLinkList(DLinkList* L)
{
DListNode* h = (*L)->next;//头节点下一个结点
if (h==NULL)
{
printf("空表....\n");
return -1;
}
while (h != NULL)
{
printf("%d ",h->data);
h = h->next;
}
}
2.4头插法建立双向链表
2.4.1原理图
2.4.2代码
//头插法建立双向链表
int headInsert(DLinkList* L,int n)
{
DListNode* h = *L;//头指针
DListNode* pnew = NULL;
int num = 0;
for (int i = 1; i <= n; i++)
{
pnew = (DLinkList)malloc(sizeof(DListNode));//分配空间
if (pnew ==NULL)
{
printf("分配空间失败");
return -1;
}
printf("请输入插入的第%d个元素:\n",i);
scanf("%d",&num);
pnew->data = num;
pnew->next = h->next;
if (h->next!=NULL)//有后继结点
{
h->next->prior = pnew;
}
pnew->prior = h;
h->next = pnew;
}
return 0;
}
2.4.3测试代码
int main()
{
DLinkList* h = NULL;
InitLinkList(&h);
headInsert(&h, 5);//头插5个节点
printLinkList(&h);
return 0;
}
2.4.4运行结果
2.5头删
2.5.1原理图
2.5.2代码
//头删
int DelHeadList(DLinkList* L,int* e)
{
DListNode* p = (*L)->next;//要删除的结点
//判断是不是空表
if (p==NULL)
{
printf("空表..\n");
return -1;
}
*e = p->data;
p->prior->next = p->next;
p->next->prior = p->prior;
free(p);
return 0;
}
2.5.3测试代码
int main()
{
DLinkList* h = NULL;
InitLinkList(&h);
headInsert(&h, 5);//头插5个节点
int e = 0;
printf("头删前:\n");
printLinkList(&h);
DelHeadList(&h,&e);
printf("\n删除的元素为:%d,头删后:\n",e);
printLinkList(&h);
return 0;
}
2.5.4运行结果
2.6尾插法建立双向链表
2.6.1原理图
2.6.2代码
//尾插法建立双向链表
int TailInsert(DLinkList* L, int n)
{
DListNode* tail = *L;//尾指针
DListNode* pnew = NULL;
int num = 0;
for (int i = 1; i <= 5; i++)
{
pnew = (DLinkList)malloc(sizeof(DListNode));//分配空间
if (pnew == NULL)
{
printf("分配空间失败");
return -1;
}
printf("请输入的第%d个插入的元素:\n",i);
scanf("%d", &num);
pnew->data = num;
tail->next = pnew;
pnew->prior = tail;
pnew->next = NULL;
tail = tail->next;
}
return 0;
}
2.6.3测试代码
int main()
{
DLinkList* h = NULL;
InitLinkList(&h);
TailInsert(&h, 5);//尾插
printLinkList(&h);
return 0;
}
2.6.4运行结果
2.7尾删
2.7.1原理图
2.7.2代码
//尾删
int DelTailList(DLinkList* L,int* e)
{
DListNode* rear = *L;
//判断是不是空表
if ((*L)->next == NULL)
{
printf("空表..\n");
return -1;
}
//找到尾节点
while (rear->next!=NULL)
{
rear = rear->next;
}
*e = rear->data;
rear->prior->next = NULL;
rear->prior = NULL;
free(rear);
}
2.7.3测试代码
int main()
{
DLinkList* h = NULL;
InitLinkList(&h);
TailInsert(&h, 5);
printf("尾删前:\n");
printLinkList(&h);
int e = 0;
DelTailList(&h,&e);//尾删
printf("\n删除的元素为:%d,尾删后:\n",e);
printLinkList(&h);
return 0;
}
2.7.4运行结果
2.8判空
2.8.1代码
//判空
void isEmpty(DLinkList* L)
{
DListNode* h = (*L)->next;//头节点下一个结点
//空表
if (h == NULL)
{
printf("空表....\n");
}
}
2.8.2测试代码
int main()
{
DLinkList* h = NULL;
InitLinkList(&h);
isEmpty(&h);
return 0;
}
2.8.3运行结果
2.9求表长
2.9.1代码
//求表长
int LinkListLength(DLinkList* L)
{
DListNode* h = (*L)->next;//头节点下一个结点
int length = 0;
//空表
if (h==NULL)
{
return 0;
}
while (h != NULL)
{
length++;
h = h->next;
}
return length;
}
2.9.2测试代码
int main()
{
DLinkList* h = NULL;
InitLinkList(&h);
headInsert(&h, 5);//头插5个节点
int length = LinkListLength(&h);
printf("\n表长:%d\n", length);
return 0;
}
2.9.3运行结果
3.0根据位置插入元素
3.0.1原理图
3.0.2代码
//根据位置插入元素
int insertNode(DLinkList* L, int i, int e)
{
if (i < 1)
return -1;
DListNode* p = *L; //p为指向当前结点的指针
int j = 0; //p指针指向的当前结点,当前位置为头结点
//寻找第i-1个节点
while (p != NULL && j < i-1) {
p = p->next;
j++;
}
DListNode* s = (DListNode*)malloc(sizeof(DListNode)); //创建新结点
if (s == NULL)
{
return -1;
}
s->data = e;
s->next = p->next;
p->next->prior = s;
s->prior = p;
p->next = s;
return 0;
}
3.0.3测试代码
int main()
{
DLinkList* h = NULL;
InitLinkList(&h);
TailInsert(&h, 5);//尾插五个元素
printf("插入元素之前:\n");
printLinkList(&h);
insertNode(&h,3,66);
printf("\n插入元素之后:\n");
printLinkList(&h);
return 0;
}
3.0.4运行结果
3.1根据位置删除元素
3.1.1原理图
3.1.2代码
//根据位置删除元素
int delNodeByLoc(DLinkList* L, int i, int* e)
{
DListNode* p = *L;
DListNode* q = NULL;
//判断删除位置是否合法
int length = LinkListLength(L);
if (i<1||i>length)
{
printf("删除位置不合法...\n");
return -1;
}
//寻找第i-1个节点
int j = 0;
while (p!=NULL&&j<i-1)
{
p = p->next;
j++;
}
q = p->next;//要删除的节点
*e = q->data;
p->next = q->next;
//这里要做判断,如果是删除的最后一个结点,
//那么删除结点的后继结点的前趋就不用指向被删结点的前一个结点了
if (q->next!=NULL)
{
q->next->prior = p;
}
free(q);
return 0;
}
3.1.3测试代码
int main()
{
DLinkList* h = NULL;
InitLinkList(&h);
TailInsert(&h, 5);
int e = 0;
delNodeByLoc(&h, 5, &e);
printf("\n删除的元素为:%d\n", e);
printLinkList(&h);
return 0;
}
3.1.4运行结果
3.2根据位置查询元素
3.2.1原理图
3.2.2代码
//根据位置查询元素
int GetElmByLoc(DLinkList* L, int i, int* e)
{
DListNode* p = *L;
//判断查询位置是否合法
int length = LinkListLength(L);
if (i<1 || i>length)
{
printf("查询位置不合法...\n");
return -1;
}
//找到第i个节点
int j = 0;
while (j<i)
{
p = p->next;
j++;
}
*e = p->data;
return 0;
}
3.2.3测试代码
int main()
{
DLinkList* h = NULL;
InitLinkList(&h);
TailInsert(&h, 5);
int e = 0;
GetElmByLoc(&h, 5, &e);
printf("\n查询的元素为:%d\n",e);
return 0;
}
3.2.4运行结果
3.3清空双向链表
3.3.1原理图
3.3.2代码
//清空双向链表
int clearList(DLinkList* L)
{
DListNode* p = *L;
DListNode* q = NULL;
//判断是不是空表
if (p->next == NULL)
{
printf("空表..\n");
return -1;
}
while (p->next!=NULL)
{
q = p->next;
p->next = q->next;
free(q);
}
return 0;
}
3.3.3测试代码
int main()
{
DLinkList* h = NULL;
InitLinkList(&h);
TailInsert(&h, 5);
printf("清空前:\n");
printLinkList(&h);
clearList(&h);
printf("\n清空后:\n");
printLinkList(&h);
return 0;
}
3.3.4运行结果
注意:如果想要销毁双向链表,清空双链表后把头结点也释放掉就可以了