双向链表是指在前驱和后继方向都能游历(遍历)的线性链表。
双向链表每个结点结构:
前指针域 prior | 数据域data | 后指针域 next
前指针指向前驱方向,上一个结点;后指针指向后继方向,也就是下一个结点。
这样指针就可与任意访问后面或者前面的,指针就可以不受单链表的约束,向前或向后移动。
双向链表通常采用带表头结点的循环链表形式。
头文件
#ifndef DOUBLELINKLIST_H
#define DOUBLELINKLIST_H
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define SUCCESS 10000
#define FAILURE 10001
typedef int ElemType; //把int整形名字改为ElemType(主要是元素) 方便书写
struct Node
{
ElemType data; //数据域
struct Node *next; //定义一个指针指向结构体struct Node(指针域)
struct Node *prior; // 定义一个前指针指向结构体的struct Node 的前面一个结点。
};
typedef struct Node node; //改名字,把struct Node 改为 node。方便书写
typedef struct Node *pNode; //把struct Node * 改为pNode (它是一个指针)
int InitLink(pNode *h);
int InsertLink(pNode h, int p, int num);
int TraverseLink(pNode h);
int GetElem(pNode h, int p);
int LocateElem(pNode h, int e);
int LengthLink(pNode h);
int PriorElem(pNode h, int num);
int NextElem (pNode h, int num);
void ReverseLink(pNode h);
int LinkDel (pNode h, int p);
int ClearLink(pNode h);
int Destory(pNode *h);
#end
调用子函数实现功能的函数文件
#include"DoubleLinkList.h"
int InitLink(pNode *h)
{
if(NULL == h)
return FAILURE;
*h = (pNode)malloc(sizeof(pNode) * 1);
if(NULL == *h)
return FAILURE;
(*h) -> next = NULL;
(*h) -> prior = NULL;
return SUCCESS;
}
int InsertLink(pNode h, int p, int num)
{
if(NULL == h)
return FAILURE;
pNode t = h;
int k = 1; //指针移动的次数
while(t && k < p)
{
t = t -> next;
k++
}
if(p <= 0 || k > p || !t)
return FAILURE;
pNode n = (pNode)malloc(sizeof (pNode) *1);
t -> data = num;
n-> next = t ->next;
n -> prior = t;
t -> next = n;
if(n -> next)
t -> next -> prior = n;
return SUCCESS;
}
int Traverse(pNode h)
{
if(NULL == h)
return FAILURE;
pNode t = h ;
while(t)
{
printf("%d\n", t -> data);
t = t -> next;
}
printf("\n");
return SUCCESS;
}
int GetElem(pNode h, int p);
{
if(NULL == h)
return FAILURE;
if(p <= 0)
return FAILURE;
pNode t = h ;
int k = 0;
while(k < p && t != NULL)
{
t = t -> next;
k++;
}
if(!t) // p的值太大 t都已经为空了,还没找到位置
return FAILURE;
int e = t -> data;
return e;
}
int LocateLink(pNode h, int e)
{
if(NULL == h)
return FAILURE;
pNode t = h -> next;
int k = 1;
while(t)
{
if(t -> data == e)
{
return i;
}
t = t ->next;
i++;
}
return FAILURE;
}
int LengthLink(pNode h);
{
if(NULL == h)
return FAILURE;
pNode t = h -> next;
int i = 1;
while(t)
{
t = t -> next;
i++;
}
return i - 1;
}
int PriorElem(pNode h, int num)
{
if(NULL == h)
return FAILURE;
pNode t = h -> next;
while(t )
{
if(num == t ->data)
{
return t ->prior -> data;
}
t = t -> next;
}
if(!t) //只有一个结点
{
return FAILURE;
}
return FAILURE;
}
int NextElem(pNode h, int num)
{
if(NULL == h)
return FAILURE;
pNode t = h -> next;
while(t)
{
if(num == t -> data)
{
return t -> next;
}
t = t ->next -> data;
}
return FAILURE;
}
void ReverseLink(pNode h);
{
if(NULL == h)
return FAILURE;
pNode t = h -> next;
h -> next = NULL;
int i = 0;
while(t)
{
pNode q = p;
p = p -> next;
q -> next = h -> next;
q -> prior = h ;
h -> next = q;
}
if(0 != i)
{
q -> next -> prior = q;
i++;
}
}
int LinkDel(pNode h, int p)
{
if(NULL == h)
return FAILURE;
pNode t = h -> next;
int k = 1;
while(t != NULL && k < p)
{
t = t -> next;
k++;
}
if(t == NULL || k > p || t -> next == NULL) //p的值太大 p的值太小 无法删除最后的下一个结点
{
return FAILURE;
}
pNode n = t -> next;
int e = n -> data;
t -> next = n -> next;
n -> next ->prior = t;
free(n);
return e;
}
int ClearLink(pNode h)
{
if(NULL == h)
return FAILURE;
pNode t = h -> next;
while(t)
{
h -> next = t -> next; //头结点指向第二个节点
free(t); //释放这个位置的元素的空间
t = t ->next; //接着指向下一个结点,进行下一次循环
}
return SUCCESS;
}
int DestoryLink(pNode *h)
{
if(NULL == h)
return FAILURE;
free(*h);
*h = NULL;
return SUCCESS;
}
主函数文件
#include "LinkList.h"
int main()
{
srand (time (NULL)); //随机时间随机数字函数
pNode head = NULL; //定义链表的头指针
int ret ;
//链表初始化
ret = InitLink(&head);
if(SUCCESS == ret)
{
printf("链表初始化成功\n");
}
else
{
printf("链表初始化失败!\n");
}
//指定位置插入元素(这里是去全插入,相当于把数据传给链表)
int i, num;
for (i =0; i < 7; i++)
{
num = rand () %10;
ret = InsertLink(head, i+1, num); // 尾插法
// ret = InsertLink(head, 1, num); //头插法
if (FAILURE == ret)
{
printf("插入元素%d失败\n". num);
}
else
{
printf("插入元素%d成功\n", num);
}
}
// 根据位置查找元素
int p = 6;
ret = GetElem(head, p); //获取指定元素的位置
if (FAILURE == ret)
{
printf("第%d个元素不存在\n", p);
}
else
{
printf("第%d个元素是%d\n", p, ret);
}
//根据元素查找位置
num = 6;
ret = LocateElem(head, num); //返回指定元素的位置
if(FAILURE == ret)
{
printf("元素%d不存在\n", num);
}
else
{
printf("元素%d是第%d个元素\n", num);
}
printf("链表的长度是%d\n", LengthLink(head));
//根据元素查找元素的前驱
num = 6;
ret = PriorElem (head, num); //返回指定元素的前驱
if(FAILURE == ret)
{
printf("%d没有前驱\n", num);
}
else
{
printf("%d的前驱是%d\n", num, ret);
}
//根据元素查找元素的后继结点
num = 6;
ret = NextElem(head, num);
if(FAILURE == ret)
{
printf("%d没有后继结点\n", num);
}
else
{
printf("%d的后继结点是%d\n", num, ret);
}
//删除指定位置的元素
for(i = 0; i < 3; i++)
{
p = rand() %4; //随机产生一个位置
ret = LinkDel(head, p);
if(FAILURE == ret)
{
printf("删除第%d个元素失败\n", p);
}
else
{
prinntf("删除第%d个结点成功,元素是%d\n", p , ret);
}
}
//清空链表
ret = ClearLink(head);
if(FAILURE == ret)
{
printf("清空链表失败\n");
}
else
{
printf("清空链表成功\n");
}
//销毁链表
ret = DestoryLink(&head);
if(FAILURE == ret)
{
printf("清除失败\n");
}
else
{
printf("清除成功\n");
}
return 0;
}