4.双向链表
双向链表是每个结点除后继指针域外还有一个前驱指针域,它有带头结点和不带头结点,循环和非循环结构,双向链表是解决查找前驱结点问题的有效途径。
结点结构如图示:
下图是带头结点的循环双向链表的结构,可见,其前驱指针和后继指针各自构成自己的循环单链表。
设指针p指向第i个数据元素结点,则p->next指向第i+1个数据元素结点,p->next->prior仍指向第i个数据元素结点,即p->next->prior=p;同样p->prior->next=p。
循环双向链表的插入过程如图示:
删除过程如图示:
typedef int DataType; //定义抽象数据类型
//节点的结构体
typedef struct Node
{
DataType data; //节点的数据域
struct Node *next; //节点的尾指针域
struct Node *prior; //
} SLNode;
//初始化ListInitiate(head)
void ListInitiate(SLNode **head)
{
*head = (SLNode *)malloc(sizeof(SLNode));
(*head)->prior = *head; //构成前驱指针循环链表
(*head)->next = *head; //构成后继指针循环链表
}
//求当前数据元素个数ListLength(head)
int ListLength(SLNode *head)
{
SLNode *p = head;
int size = 0;
while (p->next != head)
{
p = p->next;
size++;
}
return size;
}
//插入数据元素
int ListInsert(SLNode *head, int i, DataType x)
//在带头结点的双向循环链表head的第i个结点前,插入一个存放
//数据元素x的结点,插入成功返回1,失败返回0
{
SLNode *p, *s;
int j;
p = head->next;
j = 0;
while (p != head && j < i)
{
p = p->next;
j++;
}
if (j != i)
{
printf("参数i错误!");
return 0;
}
s = (SLNode *)malloc(sizeof(SLNode));
s->data = x;
s->prior = p->prior; //新结点指向前一个结点(中——>前)
p->prior->next = s; //新结点结点指向前一个结点(前->中)
s->next = p; //新节点指向后结点 (中->后)
p->prior = s; //后结点指向新节点 (后->中)
return 1;
}
//取数据元素ListGet(head, i, x)
int ListGet(SLNode *head, int i, DataType *x)
{
SLNode *p;
int j;
p = head;
j = -1;
while (p->next != head && j < i)
{
p = p->next;
j++;
}
if (j != i)
{
printf("取元素位置参数错!");
return 0;
}
*x = p->data;
return 1;
}
//删除ListDelete(head, i, x)
int ListDelete(SLNode *head, int i, DataType *x)
{
SLNode *p;
int j;
p = head->next;
j = 0;
while (p->next != head && p->next ->next != head&& j < i )
{
p = p->next;
j++;
}
if (j != i)
{
printf("删除数据元素为值参数出错!");
return 0;
}
*x = p->data;
p->prior->next = p->next;
p->next -> prior = p->prior;
free(p);
return 1;
}
//撤销内存空间DestroyList(SLNode **head)
void DestoryList(SLNode **head)
{
SLNode *p,*q;
int i,n=ListLength(*head);
p=*head;
for(i=0;i<=n;i++)
{
q=p;
p=p->next;
free(p);
}
*head=NULL;
}
5.静态链表
在数组中增加一个(或两个)指针域用来存放下一个(或上一个)数据元素在数组中的下标,从而构成用数组构造的单链表。因为数组内存空间的申请方式是静态的,所以称为静态链表,增加的指针称做仿真指针。
结构如下:
#define TRUE 1
#define FALSE 0
#define MAX_LEN 100
typedef int Status;
typedef int ElemType;
typedef struct _tag_staticlist
{
ElemType data;
int cur;
} StaticList, List[MAX_LEN];
/* Init StaticList */
Status InitList(StaticList *list)
{
int i = 0;
for (i = 0; i < MAX_LEN - 1; i++)
{
list[i].cur = i + 1;
list[i].data = 0; //此处初始化为0 是为了方便观看 实际中ElemType不一定是int型
}
list[MAX_LEN - 1].cur = 0;
list[MAX_LEN - 1].data = 0;
return TRUE;
}
/* Display StaticList */
void DisplayList(StaticList *list)
{
int i = 0;
for (i = 0; i < MAX_LEN; i++)
{
printf("%d.cur = %d, %d.data = %d\n", i, list[i].cur, i, list[i].data);
}
return;
}
/* Malloc StaticList, Get Free Space */
int Malloc_SL(StaticList *list)
{
int ret = 0;
ret = list[0].cur;
list[0].cur = list[ret].cur; // 指向下一个节点的cur
return ret;
}
/* Free StaticList, Free Space */
Status Free_SL(StaticList *list, int j)
{
list[j].cur = list[0].cur; // 保存备用链表第一个节点下一个节点cur
list[0].cur = j; // j成为备用链表的首节点下标
return TRUE;
}
/* Insert StaticList */
Status InsertList(StaticList *list, int pos, ElemType data)
{
int i = 0;
int j = 0;
int k = MAX_LEN - 1;
if (pos < 1 || NULL == list || pos >= MAX_LEN - 1)
return FALSE;
j = Malloc_SL(list); // Malloc cur
list[j].data = data; // Insert data
for (i = 1; i < pos; i++)
{
k = list[k].cur;
}
list[j].cur = list[k].cur;
list[k].cur = j;
return TRUE;
}
Status InsertList(StaticList *list, int pos, ElemType *ret)
{
int i = 0;
int j = 0;
int k = MAX_LEN - 1;
if (pos < 1 || NULL == list || pos >= MAX_LEN - 1)
return FALSE;
for (i = 1; i < pos; i++)
{
k = list[k].cur;
}
j = list[k].cur;
*ret = list[j].data;
Free_SL(list, j);
return TRUE;
}