一、代码
/*
*linkedlist
*2018/11/29:head_insert;tail_insert;reverse;traversal;
*2018/11/30:insert;dele;
*xinchiwu
*/
#include <stdlib.h>
#include <stdio.h>
typedef struct linkedlistnode
{
struct linkedlistnode *prev;
char data;
struct linkedlistnode *next;
}linkedlist;
linkedlist *head, *tail;
void head_insert()//头插入法;通过全局变量,返回头指针和尾指针;
{
char ch;
linkedlist *q;
q = NULL;
head = NULL;
tail = NULL;
printf("请输入头插法要插入的字符:\n");
ch = getchar();
while (ch != '\n')
{
linkedlist *s = (linkedlist*)malloc(sizeof(linkedlist));
if (s != 0)
{
s->next = head;
s->data = ch;
s->prev = NULL;
head = s;
if (s->next == NULL)
{
tail = s;
q = tail;
}
else
{
q->prev = s;
q = q->prev;
}
ch = getchar();
}
}
}
void traversal()//遍历;通过头指针读取结点数据;
{
linkedlist *s;
char ch;
printf("正序输出的链表如下:\n");
while (head != NULL)
{
ch = head->data;
printf("%c",ch);
s = head;
if (head != NULL)
{
head = head->next;
s->next = NULL;
free(s);
}
}
}
void tail_insert()//尾插入法;通过全局变量,返回头指针和尾指针;
{
linkedlist *p;
p = head;
char ch;
head = NULL;
tail = NULL;
printf("请输入尾插法要插入的字符:\n");
ch = getchar();
while (ch != '\n')
{
linkedlist *s = (linkedlist*)malloc(sizeof(linkedlist));
if (s != 0)
{
s->prev = p;
s->data = ch;
s->next = NULL;
tail = s;
ch = getchar();
if (head == NULL)
{
head = s;
p = head;
}
else
{
p->next = s;
p = p->next;
}
}
}
}
void reversal()//倒序;通过尾指针读取节点数据;
{
linkedlist *s;
char ch;
printf("倒序输出的链表如下:\n");
while (tail != NULL)
{
ch = tail->data;
printf("%c", ch);
s = tail;
if (tail != NULL)
{
tail = tail->prev;
s->prev = NULL;
free(s);
}
}
}
void insert()//向链表中插入节点;n<=0,插在头节点处;n>=链表长度,插在尾结点处;
{
printf("请输入要插入的位置:\n");
int n;
scanf_s("%d", &n);
linkedlist *s=(linkedlist*)malloc(sizeof(linkedlist));
linkedlist *p, *q;
p = q = NULL;
char ch;
getchar();
printf("请输入要插入的字符:\n");
ch = getchar();
s ->data= ch;
if (n <= 1)
{
head->prev = s;
s->next = head;
s->prev = NULL;
head = s;
}
else
{
for (int i = n - 1; i > 0; i--)
{
if (i==n-1)
{
p = head;
q = p->next;
}
else
{
if (q->next != NULL)
{
p = p->next;
q = q->next;
}
else
{
p = p->next;
break;
}
}
}
if (p->next != NULL)
{
q->prev = s;
p->next = s;
s->next = q;
s->prev = s;
}
else
{
s->next = NULL;
tail = s;
s->prev = p;
p->next = s;
}
}
}
void dele()//删除链表中的节点;n<=0,删除头节点处;n>=链表长度,删除尾结点处;
{
printf("请输入要删除的位置:\n");
int n;
scanf_s("%d", &n);
linkedlist *p, *q, *r;
p = q = r = NULL;
if (n <= 1)
{
r = head;
head = head->next;
head->prev = NULL;
}
else
{
for (int i = n - 1; i > 0; i--)
{
if (i == n - 1)
{
p = head;
r = p->next;
q = r->next;
}
else
{
if (q->next != NULL)
{
p = p->next;
r = r->next;
q = q->next;
}
else
{
p = p->next;
r = r->next;
break;
}
}
}
if (q->next != NULL)
{
q->prev = p;
p->next = q;
r->next = NULL;
r->prev = NULL;
}
else
{
p->next = NULL;
r->next = NULL;
r->prev = NULL;
tail = p;
}
}
free(r);
r = NULL;
}
int main()
{
//tail_insert();
head_insert();
insert();
//dele();
//traversal();
reversal();
getchar();
char c = getchar();
}
二、感悟
双向链表与单向链表最大的不同,就是有个prev,所以在维护节点之间的关系时,要注意两个方向的连接。相对单链表,双链表的倒序十分容易,但插入和删除并没有太大不同。