双向链表,双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
代码如下:
首先是头文件部分:
//double_link_list.h头文件
#ifndef __DOUBLE_LINK_LIST_H__
#define __DOUBLE_LINK_LIST_H__
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef struct Double
{
int data;
struct Double *prior;
struct Double *pnext;
}NODE, *PNODE;
PNODE create(PNODE phead);
void traverse_list(PNODE phead);
int is_empty(PNODE pHead);
int lenght_list(PNODE pHead);
int insert_list(PNODE pHead, int n, int val);
int delete_list(PNODE pHead, int n, int *pVal);
int* find(PNODE pHead, int a, int *sv);
void soert_list(PNODE pHead, char ch);
void Clear_list(PNODE phead);
PNODE DestroyList(PNODE pHead);
#endif // __DOUBLE_LINK_LIST_H__
接下来是函数文件:
//double_link_list.c文件
#define _CRT_SECURE_NO_WARNINGS 1
#include"double_link_list.h"
//创建链表
PNODE create(PNODE phead)
{
PNODE p = NULL;
int len = 0;
int val = 0;
phead = (PNODE)malloc(sizeof(NODE));
assert(phead);
phead->prior = phead;
phead->pnext = phead;
p = phead;
printf("请输入你所要创建双向链表节点的个数:");
scanf("%d", &len);
for (int i = 0; i < len; i++)
{
PNODE pnew = (PNODE)malloc(sizeof(NODE));
assert(pnew);
printf("输入在第%d节点的值", i + 1);
scanf("%d", &val);
pnew->data = val;
p->pnext = pnew;
pnew->prior = p;
pnew->pnext = phead;
phead->prior = pnew;
p = pnew;
}
return phead;
}
//遍历整个双向链表
void traverse_list(PNODE phead)
{
assert(phead);
PNODE p = phead->pnext;
while (p != phead)
{
printf("%d ", p->data);
p = p->pnext;
}
printf("\n");
}
//判断链表是否为空
int is_empty(PNODE pHead)
{
if (pHead == pHead->pnext)
{
return 1;
}
return 0;
}
//求链表的长度
int lenght_list(PNODE pHead)
{
int len = 0;
assert(pHead);
PNODE p = pHead->pnext;
while (p)
{
if (p != pHead)
{
len++;
p = p->pnext;
}
else
break;
}
return len;
}
//插入在某个位置插入数据
int insert_list(PNODE pHead, int n, int val)
{
assert(pHead);
PNODE p = pHead ;
int i = 0;
//在这里进行的是寻找咱们所需要插入的那个节点
while (NULL != p&&i < n - 1)
{
p = p->pnext;
i++;
}
if (n <= 0 || n>lenght_list(pHead))
{
return 0;
}
PNODE pNew = (PNODE)malloc(sizeof(NODE));
assert(pNew);
pNew->data = val;
pNew->prior = p;
pNew->pnext = p->pnext;
p->pnext->prior = pNew;
p->pnext = pNew;
if (p == pHead)
pHead = pNew;
return 1;
}
//删除指定位置节点
int delete_list(PNODE pHead, int n, int *pVal)
{
assert(pHead);
PNODE p = pHead;
int i = 0;
while (i<n)
{
p = p->pnext;
i++;
}
if (n <= 0 || n>lenght_list(pHead))
{
return 0;
}
*pVal = p->data;
//输出p节点后的节点,这里要注意的是一定要记得free;
p->prior->pnext = p->pnext;
p->pnext->prior = p->prior;
if (pHead == p)
pHead = p;
free(p);
return 1;
}
//查找某个元素的位置
int* find(PNODE pHead, int a, int *sv)
{
assert(pHead);
int count = 1;
PNODE p = pHead->pnext;
while (p != pHead)
{
p = p->pnext;
count++;
if (a == p->data)
{
*sv = count;
return sv;
}
}
return NULL;
}
//链表排序
//链表排序最适合的是冒泡排序法。
void soert_list(PNODE pHead, char ch)
{
assert(pHead);
if ('>' == ch)
{
for (PNODE p1 = pHead->pnext; p1 != pHead; p1 = p1->pnext)
{
for (PNODE p2 = pHead->pnext; p2 != pHead; p2 = p2->pnext)
{
if ((p1->data) > (p2->data))
{
int tmp = p1->data;
p1->data = p2->data;
p2->data = tmp;
}
}
}
}
else if ('<' == ch)
{
for (PNODE p1 = pHead->pnext; p1 != pHead; p1 = p1->pnext)
{
for (PNODE p2 = pHead->pnext; p2 != pHead; p2 = p2->pnext)
{
if ((p1->data) < (p2->data))
{
int tmp = p1->data;
p1->data = p2->data;
p2->data = tmp;
}
}
}
}
}
//销毁链表
PNODE DestroyList(PNODE pHead)
{
PNODE q, p;
assert(pHead);
p = q = NULL;
p = pHead;
while (p->pnext != pHead)
{
q = p->pnext;//让q指向下一个节点
p->pnext = q->pnext;//p存储了q。下一个节点的地址;
free(q);
}
free(pHead);
return NULL;
}
最后是测试函数部分:
#define _CRT_SECURE_NO_WARNINGS 1
#include"double_link_list.h"
int main()
{
PNODE phead = NULL;
int len = 0;
//测试创建双向链表
phead=create(phead);
//测试遍历双向链表
traverse_list(phead);
//测试双向链表是否为空
if (is_empty(phead) == 1)
printf("这个链表为空\n");
else
printf("这个链表不为空\n");
//测试求循环链表的长度
printf("此双向链表的长度为:\n");
len = lenght_list(phead);
printf("%d\n", len);
//测试双向插入在某个位置插入数据
int n = 0;
int val = 0;
printf("请输入你所需要插入的位置:");
scanf("%d", &n);
printf("请输入你所需要插入的数据:");
scanf("%d", &val);
if (insert_list(phead, n, val) == 0)
printf("插入失败\n");
else
printf("插入成功\n");
traverse_list(phead);
//测试双向链表删除指定位置的节点
int del_Val = 0;
printf("请输入你所需要删除的节点所在的位置:");
scanf("%d", &n);
if (delete_list(phead, n, &del_Val))
{
printf("删除元素%d成功\n", del_Val);
}
else
{
printf("删除元素%d失败\n", del_Val);
}
traverse_list(phead);
//测试双向链表元素查找,并且返回所在位置
int a = 0;
int find_position = 0;
printf("输入你所要查找的元素");
scanf("%d", &a);
if (find(phead, a, &find_position) == NULL)
printf("该双向链表中没有这一个元素。\n");
else
{
printf("所查找的元素位置位于:\n");
printf("%d\n", find_position);
}
//测试双向链表的排序
char ch = 0;
printf("选择双向链表的排序方式(输入'>'(降序)或者'<'(升序)):\n");
fflush(stdin);
scanf("%c", &ch);
soert_list(phead, ch);
traverse_list(phead);
//测试销毁链表
phead = DestroyList(phead);
system("pause");
return 0;
}
小白一枚,希望大家多多指教。