双向链表
郝斌老师课程没有双向链表内容,我参考大话数据结构把双向链表进行简单实现,其实双向链表跟单链表类似,没有特别难的地方,只需要自己画图,把每一步程序的意思弄明白,并不难。
需要注意的有两个地方:双向链表的插入和删除,插入节点时前驱和后驱赋值顺序,删除节点时前驱和后驱的赋值顺序。另外还有就是遍历的时候,注意终止条件,因为是双向链表,如果不记录头结点,可能会一直循环下去。
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<stdbool.h>
typedef struct Node
{
int data;
struct Node * prior;
struct Node * pnext;
}NODE, * PNODE;
PNODE creat_list()
{
int len = 0;
int i = 0;
int val = 0;
PNODE pHead = (PNODE) malloc(sizeof(NODE));//注意后续释放
if(NULL == pHead)
{
printf("malloc err!\n");
exit(-1);
}
PNODE pTail = pHead;
pTail->prior = NULL;
pTail->pnext = NULL;
printf("请输入您需要创建的链表节点的个数:len = ");
scanf("%d",&len);
printf("请输入第1个节点的数据:val = ");
scanf("%d",&val);
PNODE p1 = (PNODE)malloc(sizeof(NODE));
if(NULL == p1)
{
printf("分配失败,程序终止!\n");
exit(-1);
}
p1->data = val;
pTail->pnext = p1;
pTail = p1;
for(i = 2; i <= len; i++)
{
printf("请输入第%d个节点的数据:val = ",i);
scanf("%d",&val);
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if(NULL == pNew)
{
printf("分配失败,程序终止!\n");
exit(-1);
}
pNew->data = val;
pTail->pnext = pNew; //当前尾节点的pnext指向新节点
pNew->prior = pTail;//新节点的prior指向尾节点
pNew->pnext = p1; //新节点的pnext指向头节点
p1->prior = pNew; //头节点的prior指向新节点
pTail = pNew; //新节点变为尾节点
}
return pHead;
}
/* 双链表一般不会为空的,所以判断空的就暂不实现
bool is_empty(PNODE pHead)
{
if(NULL == pHead->pNext)
return true;
else
return false;
}*/
void traverse_list(PNODE pHead)
{
PNODE p = pHead->pnext;
PNODE pHead1 = p;//记录第一个有效节点,防止一直循环下去
do
{
printf("%d\t", p->data);
p = p->pnext;
}while(p != pHead1);
printf("\n");
}
int length_list(PNODE pHead)
{
PNODE p = pHead->pnext;
PNODE pHead1 = p;//同样是记录首节点,防止死循环
int len = 0;
do
{
len++;
p = p->pnext;
}while(p != pHead1);
return len;
}
int insert_list(PNODE pHead, int pos, int val)
{
int i = 0;
PNODE p = pHead;
PNODE pEnd = pHead;
//首先调整p指向的位置
//其实这地方最好不要插入第一个位置,本实现最后结果是插在最后
if(pos == 1)
{
p = p->pnext;
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if(NULL == pNew)
{
printf("malloc failed!\n");
exit(-1);
}
pNew->data = val;
pNew->pnext = p;
pNew->prior = p->prior;
p->prior->pnext = pNew;
p->prior = pNew;
return true;
}
do
{
p = p->pnext;
i++;
}while(pHead != pEnd && i < pos - 1);
//这时候p已经指向pos的位置
if(i > pos-1 )
return false;
PNODE pNew = (PNODE)malloc(sizeof(NODE));
if(NULL == pNew)
{
printf("分配内存失败!\n");
exit(-1);
}
pNew->data = val;
pNew->pnext = p->pnext;//新节点的后驱指向p的后驱
pNew->prior = p;//新节点的前驱指向p
p->pnext->prior = pNew;//p的后驱的前驱指向新节点
p->pnext = pNew;//p的后驱指向新节点
return true;
}
//只实现了在链表中部的实现,首节点的删除未实现,即pos>=2
int delete_list(PNODE pHead, int pos, int *val)
{
int i = 0;
PNODE p = pHead;
PNODE pHead1 = p;
do
{
p = p->pnext;
++i;
}while(i <= pos-1 && p != pHead1);
*val = p->data;
p->pnext->prior = p->prior;//要删除节点p的后驱的前驱指向p的前驱
p->prior->pnext = p->pnext;//要删除节点p的前驱的后驱指向p的后驱
free(p);
return true;
}
int main(void)
{
PNODE pHead;
int val;
pHead = creat_list();
traverse_list(pHead);
int ret;
ret = insert_list(pHead, 2, 11);
if(ret < 0)
{
printf("插入失败,ret = %d\n",ret);
return -1;
}
traverse_list(pHead);
delete_list(pHead,2,&val);
traverse_list(pHead);
return 0;
}