// 双向链表.cpp : 定义控制台应用程序的入口点。
//带头结点的双向链表
#include "stdafx.h"
#include "malloc.h"
typedef int DataType;//宏定义:便于更改数据类型,提高程序复用性
/*定义双链表的结点类型,整个部分的实质就是用户自定义数据类型*/
/*系统并不为Node整体分配内存空间,内存空间实际上是变量所占内存空间之和*/
/*优点:真正的动态,不需要处理固定容量的问题;缺点:相比顺序表而言丧失了随机存取的能力*/
typedef struct Node {
DataType data;//定义数据域变量
struct Node *prior;//定义前驱指针
struct Node *next;//定义后继指针
}DNode,* PDNode,* DLinkList;//DNde和*PDNode都是代表Struct Node数据类型,其区别在于:前者表示类型名,而后者表示指向Struct Node数据类型的指针
/*创建双向链表:*/
/*头插法创建双向链表:直接使得头结点的前驱结点和后继结点指向头结点*/
/*DLinkList Create_DLinkList(DLinkList &h)
{
DLinkList p;
DataType data;
h = (DLinkList)malloc(sizeof(DNode));
h->prior = NULL;
h->next =h;
printf("input the value of data:\n");
scanf_s("%d",&data);
while (data!=0)
{
p= (DLinkList)malloc(sizeof(DNode));
p->data = data;
p->next = h->next;
p->prior = h;
h->next = p;
h->prior = h;
printf("input the value of new data:\n");
scanf_s("%d",&data);
}
return h;
}*/
/*尾插法创建双向链表:*/
DLinkList Create_RDLinkList(DLinkList &h)
{
DLinkList p,r;
DataType data;
//创建头结点
h = (DLinkList)malloc(sizeof(DNode));
h->prior = h;
h->next = h;
r = h->next;
printf("input the data:\n");
scanf_s("%d",&data);
while (data!=0)
{
//创建新的结点
if (!(p = (DLinkList)malloc(sizeof(DNode))))
return NULL;
p->data = data;
r->next = p;
p->prior =r;
r = p;
printf("input the value of new data:\n");
scanf_s("%d", &data);
}
r->next = NULL;
return h;
}
/*遍历双向链表:通过右移指针,直到指针域为空*/
DLinkList TraverseList(DLinkList h)//h为指向链表的头指针
{
PDNode p = h->next;//将头指针指向第一个结点
while (p !=NULL)
{
printf("%d \t", p->data);
p = p->next;//右移指针
}
printf("\n");
return h;
}//时间复杂度为o(1)
/*插入:1)算法思想:1.将待插入点的前驱指针指向p的前驱结点:q->prior=p->prior;
2.将p前驱结点的后继指针指向新结点q:p->prior->next=q;
3.将p的前驱指针指向q:p->prior=q;
4.将q的后继指向p:q->next=p;
2)时间复杂度:o(1):
*/
int ListInsert(DLinkList &h, int pos, DataType item)//h为指向双向链表的指针,pos为插入位置,item为待插入的数据元素
{
PDNode p = h->next,q;//p指向第一个结点
int j=0;
while (p!=NULL && j < pos-1)//若指针不是头指针且没有超过插入位置坐标,执行此循环,否则退出
{
p = p->next;//指针右移,寻找待插入点
j++;
}
if (pos<1 || j !=pos-1)//当指针指向头指针,或者位置大于插入位置坐标时
{
printf("插入位置不合法!\n");
return 0;//返回类型
}
if(!(q = (PDNode)malloc(sizeof(DNode))))//为新结点动态分配内存空间,q为指向新结点的指针,PDNode为新结点指针,DNode为链表
return 0;
q->data = item;//给数据域赋值
q->prior = p->prior;//将p的前驱指针给q的前驱指针
p->prior->next = q;//将p的前驱结点的后继指针指向q
q->next = p;//将q的后继指针指向p
p->prior = q;//将p的前驱指针指向q
return 1;
}
/*删除某个位置上的元素:1.先移动指针找到位置;2.s=p;3.p->prior->next=p->next;4.p->next->prior=p->prior;5.free(s)
时间复杂度:o(1)
优缺点:*/
DLinkList Del_DLinkList(DLinkList &h, int i)
{
DLinkList p=h->next,s;
DataType j=0;
while (p!=NULL && j<i-1)
{
j++;
p = p->next;
}
if (i<1 || j !=i-1)
{
printf("删除的位置不合法");
}
s = p;
p->prior->next = p->next;
p->next->prior = p->prior;
free(s);
return h;
}
int main()
{
DLinkList h;//使头结点为空
Create_RDLinkList(h);
printf("插入操作前双向链表的数据元素:\n");
TraverseList(h);
printf("插入操作后双向链表的数据元素:\n");
ListInsert(h,2,100);
TraverseList(h);
Del_DLinkList(h, 4);
TraverseList(h);
return 0;
}