概念
带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了。 它与单链表的最大区别就是每个节点可以指向该节点的前驱节点。链表为空时,至少还有一个头结点(该节点不存储有效数据,仅仅用来表示链表的头)。头结点的前驱与后继都是自己本身;链表不为空时,头结点的前驱就是尾结点,后继是第一个节点。尾结点的前驱是倒数第二个节点,后继是头结点所以整个链表是一个循环的,不存在指向空的节点.
创建一个新的节点
ListNode* BuyNewNode ( x) {
ListNode* NewNode = ( ListNode* ) malloc ( sizeof ( ListNode) ) ;
if ( NewNode == NULL ) {
printf ( "申请空间失败!\n" ) ;
assert ( 0 ) ;
}
NewNode-> _data = x;
NewNode-> _next = NULL ;
NewNode-> _prev = NULL ;
return NewNode;
}
创建一个新的链表
ListNode* ListCreate ( ) {
ListNode* NewNode = ( ListNode* ) malloc ( sizeof ( ListNode) ) ;
if ( NewNode == NULL ) {
printf ( "申请空间失败!\n" ) ;
assert ( 0 ) ;
}
NewNode-> _data = 0 ;
NewNode-> _next = NewNode;
NewNode-> _prev = NewNode;
return NewNode;
}
双向链表销毁
void ListDestory ( ListNode* pHead) {
assert ( pHead) ;
ListNode* cur = pHead-> _next;
while ( cur != pHead) {
ListNode* next = cur-> _next;
free ( cur) ;
cur = next;
}
free ( pHead) ;
}
双向链表打印
void ListPrint ( ListNode* pHead) {
assert ( pHead) ;
ListNode* cur = pHead-> _next;
while ( cur != pHead) {
printf ( "%d->" , cur-> _data) ;
cur = cur-> _next;
}
printf ( "NULL\n" ) ;
}
双向链表尾插
void ListPushBack ( ListNode* pHead, LTDataType x) {
assert ( pHead) ;
ListInsert ( pHead, x) ;
}
双向链表尾删
void ListPopBack ( ListNode* pHead) {
assert ( pHead) ;
ListErase ( pHead-> _prev) ;
}
双向链表头插
void ListPushFront ( ListNode* pHead, LTDataType x) {
assert ( pHead) ;
ListInsert ( pHead-> _next, x) ;
}
双向链表头删
void ListPopFront ( ListNode* pHead) {
assert ( pHead) ;
ListErase ( pHead-> _next) ;
}
双向链表查找
ListNode* ListFind ( ListNode* pHead, LTDataType x) {
assert ( pHead) ;
ListNode* cur = pHead-> _next;
while ( cur != pHead) {
if ( cur-> _data == x) {
return cur;
}
else {
cur = cur-> _next;
}
}
return NULL ;
}
双向链表在pos的前面进行插入
void ListInsert ( ListNode* pos, LTDataType x) {
ListNode* NewNode = BuyNewNode ( x) ;
ListNode* prev = pos-> _prev;
prev-> _next = NewNode;
NewNode-> _prev = prev;
NewNode
-> _next = pos;
pos-> _prev = NewNode;
}
双向链表删除pos位置的节点
void ListErase ( ListNode* pos) {
ListNode* prev = pos-> _prev;
ListNode* next = pos-> _next;
free ( pos) ;
prev-> _next = next;
next-> _prev = prev;
}
运行结果
完整代码
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int LTDataType;
typedef struct ListNode
{
LTDataType _data;
struct ListNode* _next;
struct ListNode* _prev;
} ListNode;
ListNode* BuyNewNode ( ) ;
ListNode* ListCreate ( ) ;
void ListDestory ( ListNode* pHead) ;
void ListPrint ( ListNode* pHead) ;
void ListPushBack ( ListNode* pHead, LTDataType x) ;
void ListPopBack ( ListNode* pHead) ;
void ListPushFront ( ListNode* pHead, LTDataType x) ;
void ListPopFront ( ListNode* pHead) ;
ListNode* ListFind ( ListNode* pHead, LTDataType x) ;
void ListInsert ( ListNode* pos, LTDataType x) ;
void ListErase ( ListNode* pos) ;
#include "doublelist.h"
ListNode* BuyNewNode ( x) {
ListNode* NewNode = ( ListNode* ) malloc ( sizeof ( ListNode) ) ;
if ( NewNode == NULL ) {
printf ( "申请空间失败!\n" ) ;
assert ( 0 ) ;
}
NewNode-> _data = x;
NewNode-> _next = NULL ;
NewNode-> _prev = NULL ;
return NewNode;
}
ListNode* ListCreate ( ) {
ListNode* NewNode = ( ListNode* ) malloc ( sizeof ( ListNode) ) ;
if ( NewNode == NULL ) {
printf ( "申请空间失败!\n" ) ;
assert ( 0 ) ;
}
NewNode-> _data = 0 ;
NewNode-> _next = NewNode;
NewNode-> _prev = NewNode;
return NewNode;
}
void ListDestory ( ListNode* pHead) {
assert ( pHead) ;
ListNode* cur = pHead-> _next;
while ( cur != pHead) {
ListNode* next = cur-> _next;
free ( cur) ;
cur = next;
}
free ( pHead) ;
}
void ListPrint ( ListNode* pHead) {
assert ( pHead) ;
ListNode* cur = pHead-> _next;
while ( cur != pHead) {
printf ( "%d->" , cur-> _data) ;
cur = cur-> _next;
}
printf ( "NULL\n" ) ;
}
void ListPushBack ( ListNode* pHead, LTDataType x) {
assert ( pHead) ;
ListInsert ( pHead, x) ;
}
void ListPopBack ( ListNode* pHead) {
assert ( pHead) ;
ListErase ( pHead-> _prev) ;
}
void ListPushFront ( ListNode* pHead, LTDataType x) {
assert ( pHead) ;
ListInsert ( pHead-> _next, x) ;
}
void ListPopFront ( ListNode* pHead) {
assert ( pHead) ;
ListErase ( pHead-> _next) ;
}
ListNode* ListFind ( ListNode* pHead, LTDataType x) {
assert ( pHead) ;
ListNode* cur = pHead-> _next;
while ( cur != pHead) {
if ( cur-> _data == x) {
return cur;
}
else {
cur = cur-> _next;
}
}
return NULL ;
}
void ListInsert ( ListNode* pos, LTDataType x) {
ListNode* NewNode = BuyNewNode ( x) ;
ListNode* prev = pos-> _prev;
prev-> _next = NewNode;
NewNode-> _prev = prev;
NewNode-> _next = pos;
pos-> _prev = NewNode;
}
void ListErase ( ListNode* pos) {
ListNode* prev = pos-> _prev;
ListNode* next = pos-> _next;
free ( pos) ;
prev-> _next = next;
next-> _prev = prev;
}
#include "doublelist.h"
void test ( ) {
ListNode* s = ListCreate ( ) ;
ListPushBack ( s, 3 ) ;
ListPushBack ( s, 4 ) ;
ListPrint ( s) ;
ListPushFront ( s, 2 ) ;
ListPushFront ( s, 1 ) ;
ListPrint ( s) ;
ListPopBack ( s) ;
ListPrint ( s) ;
ListPopFront ( s) ;
ListPrint ( s) ;
ListNode* ret = ListFind ( s, 3 ) ;
printf ( "%d\n" , ret-> _data) ;
ListInsert ( ret, 5 ) ;
ListPrint ( s) ;
ListErase ( ret) ;
ListPrint ( s) ;
ListDestory ( s) ;
}
int main ( ) {
test ( ) ;
return 0 ;
}