双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。
以下为双向链表的增删改查
head.h
#ifndef __FF_H__
#define __FF_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char datedef[20];
/*
typedef struct
{
char name[20];
int age;
int score;
}student;
*/
typedef struct Node
{
union // 数据域
{
int len; // 头结点的数据域 (链表长度)
datedef date; // 其他结点的数据域
};
struct Node *next; // 指针域
struct Node *pre;
} *dlinklist, DLinklist;
dlinklist creat(int flag); // 创建新链表
int indel(dlinklist L, dlinklist p); // p后删除 (中删)
int insert(dlinklist L, dlinklist p, datedef e); // p后插入 (中插)
void output(dlinklist L); // 正向遍历
void T_output(dlinklist L); // 逆向遍历
int h_insert(dlinklist L, datedef s); // 头插
int h_del(dlinklist L); // 头删
int r_insert(dlinklist L, datedef e); // 尾插
int r_del(dlinklist L); // 尾删
int p_find(dlinklist L, int n); // 查看位置元素
int p_update(dlinklist L, int n, datedef e); // 修改位置元素
int p_insert(dlinklist L, int n, datedef e); // 按位置插入
int p_del(dlinklist L, int n); // 按位置删除
void L_free(dlinklist L); // 链表释放
#endif
fun.c
#include "head.h"
dlinklist creat(int flag) // 创建双向链表新结点
{
dlinklist L = (dlinklist)malloc(sizeof(DLinklist));
if (L == NULL)
{
return NULL;
}
if (flag == 1) // 头结点
{
L->len = 0;
}
else if (flag == 0) // 其他结点
{
strcpy(L->date, "");
}
L->next = NULL; // 初始化
L->pre = NULL;
return L;
}
int insert(dlinklist L, dlinklist p, datedef e) // p后插入 (中插)
{
dlinklist s = creat(0);
strcpy(s->date, e);
s->next = p->next;
s->pre = p;
p->next->pre = s;
p->next = s;
L->len++;
return 0;
}
int indel(dlinklist L, dlinklist p) // p后删除 (中删)
{
dlinklist q = p->next;
p->next = q->next;
q->next->pre = p;
L->len--;
free(q);
q = NULL;
return 0;
}
int h_insert(dlinklist L, datedef s) // 头插
{
if (L == NULL)
{
printf("头插失败\n");
return -1;
}
dlinklist q = creat(0);
if (q == NULL)
{
return -1;
}
strcpy(q->date, s);
q->next = L->next;
q->pre = L;
if (q->next)
{
L->next->pre = q;
}
L->next = q;
L->len++;
return 0;
}
void output(dlinklist L) // 正向遍历
{
if (L->next == NULL || L == NULL)
{
printf("遍历失败\n");
}
printf("正向遍历是:\n");
dlinklist p = L;
while (p->next)
{
p = p->next;
printf("%s\t", p->date);
}
puts("");
printf("该链表有%d个元素。\n", L->len);
}
/*
*for(int i=0;i<p->len;i++)
*{
*p=p->next;
*printf("%s\t",p->date);
*}
*puts("");
*/
void T_output(dlinklist L) // 逆向遍历
{
if (L->next == NULL || L == NULL)
{
printf("遍历失败\n");
}
printf("逆向遍历是:\n");
dlinklist p = L;
while (p->next)
{
p = p->next;
}
while (p->pre != L)
{
printf("%s\t", p->date);
p = p->pre;
}
printf("%s\t", p->date);
puts("");
printf("该链表有%d个元素。\n", L->len);
}
int r_insert(dlinklist L, datedef e) // 尾插
{
if (L == NULL)
{
printf("链表不存在\n");
return -1;
}
dlinklist p = creat(0);
p = L;
while (p->next)
{
p = p->next;
}
dlinklist s = creat(0);
strcpy(s->date, e);
s->pre = p;
p->next = s;
L->len++;
}
int h_del(dlinklist L) // 头删
{
if (L->next == NULL || L == NULL)
{
printf("删除失败\n");
return -1;
}
dlinklist p = L->next;
L->next = p->next;
if (p->next)
{
p->next->pre = L;
}
L->len--;
free(p);
p = NULL;
}
int r_del(dlinklist L) // 尾删
{
if (L == NULL || L->next == NULL)
{
printf("操作失败\n");
return -1;
}
dlinklist p = L;
while (p->next->next)
{
p = p->next;
}
dlinklist s = p->next;
p->next = NULL;
free(s);
s = NULL;
L->len--;
}
int p_insert(dlinklist L, int n, datedef e) // 按位置插入
{
if (L == NULL || n < 1 || n > L->len)
{
printf("位置不合法\n");
return -1;
}
dlinklist p = L;
for (int i = 0; i < n - 1; i++) // 找到第n-1个元素
{
p = p->next;
}
insert(L, p, e); // p后插入 (中插)
return 0;
}
int p_find(dlinklist L, int n) // 查看位置元素
{
if (L == NULL || n < 1 || n > L->len)
{
printf("位置不合法\n");
return -1;
}
dlinklist p = L;
for (int i = 0; i < n; i++)
{
p = p->next;
}
printf("你要找的第%d个元素为:%s\n", n, p->date);
return 0;
}
int p_update(dlinklist L, int n, datedef e) // 修改
{
if (L == NULL || n < 1 || n > L->len)
{
printf("位置不合法\n");
return -1;
}
dlinklist p = L;
for (int i = 0; i < n; i++)
{
p = p->next;
}
strcpy(p->date, e);
return 0;
}
int p_del(dlinklist L, int n) // 按位置删除
{
if (L == NULL || n < 1 || n > L->len)
{
printf("位置不合法\n");
return -1;
}
if (L->next == L)
{
printf("该链表为空");
return -1;
}
dlinklist p = L;
for (int i = 0; i < n - 1; i++) // 找到第n-1个元素
{
p = p->next;
}
indel(L, p); //(中删)
return 0;
}
/*
int e_search(dlinklist L,datedef e) //查找元素位置
{
if(L==NULL||L->next==L)
{
return -1;
}
dlinklist p=L;
int n=1;
while(p->next!=L)
{
p=p->next;
if(p->date==e) 需要进行字符串比较
{
return n;
}
n++;
}
if(n>L->len)
{
return -1;
}
}
*/
void L_free(dlinklist L) // 链表释放
{
if (L == NULL)
{
return;
}
int n = L->len;
for (int i = 0; i < n; i++)
{
h_del(L); // 头删
}
free(L);
L = NULL;
}
main.c
#include "head.h"
int main(int argc, const char *argv)
{
dlinklist L = creat(1);
int n;
datedef s, e;
/*
printf("你要头插的元素个数:");
scanf("%d",&n);
for(int i=0;i<n;i++)
{
printf("你要头插的元素是:");
scanf("%s",s);
h_insert(L,s); //头插
}
output(L);
T_output(L); //逆向遍历
*/
printf("你要尾插的元素个数:");
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
printf("你要尾插的元素是:");
scanf("%s", s);
r_insert(L, s); // 尾插
}
output(L);
T_output(L);
/*
h_del(L); //头删
output(L);
r_del(L); //尾删
output(L);
*/
printf("你要查看第几个元素");
scanf("%d", &n);
p_find(L, n); // 查看位置元素
printf("你要在哪个位置插入元素:");
scanf("%d", &n);
printf("你要插入的元素是:");
scanf("%s", e);
p_insert(L, n, e); // 按位置插入
output(L);
T_output(L);
printf("你要修改第几个元素");
scanf("%d", &n);
printf("你要将该元素改为:");
scanf("%s", e);
p_update(L, n, e); // 修改位置元素
output(L);
printf("你要删除哪个位置的元素:");
scanf("%d", &n);
p_del(L, n); // 按位置删除
output(L);
//
//
L_free(L); // 链表释放
}