循环链表的实现及链表面试题二
链表
循环链表的实现
双向带头循环链表的优越性
双向循环链表:有两个指针,一个指向前一个节点,一个指向后一个节点。
值得注意的是双向带头循环链表为空时,两个指针指向head本身。
优点:在于可以对任意给定的节点取其前面节点和后面节点的位
置,由于可以轻易得到前后节点的位置,所以在节点的插入和删除中它的操作就相对简单。其中(头插是插在头节点head的后面,尾插是插在头节点head的前面)
缺点:是每个节点都需要保存prev和next,因此需要开辟更多的空间。
其本质:是用空间换取时间
程序部分
.h文件
# pragma once
// 带头 + 双向 + 循环链表增删查改实现
typedef int DataType;
typedef struct ListNode Node;
typedef struct ListNode
{
DataType data;
struct ListNode* next;
struct ListNode* prev;
};
// 创建返回链表的头结点.
Node* DListCreate();
// 双向链表销毁
void DListDestory(Node* pHead);
// 双向链表打印
void DListPrint(Node* pHead);
// 双向链表尾插
void DListPushBack(Node* pHead, DataType x);
// 双向链表尾删
void DListPopBack(Node* pHead);
// 双向链表头插
void DListPushFront(Node* pHead, DataType x);
// 双向链表头删
void DListPopFront(Node* pHead);
// 双向链表查找
Node* DListFind(Node* pHead, DataType x);
// 双向链表在pos的前面进行插入
void DListInsert(Node* pos, DataType x);
// 双向链表删除pos位置的节点
void DListErase(Node* pos);
.c文件
#include "SXDList.h"
#include <stdio.h>
#include <malloc.h>
#include <assert.h>
// 创建返回链表的头结点.
Node* DListCreate(DataType data)
{
Node* newNode = (Node*)malloc(sizeof(Node));
if (NULL == newNode)
{
assert(0);
return NULL;
}
newNode->data = data;
newNode->next = NULL;
newNode->prev = NULL;
return newNode;
}
//双向带头循环的初始化
void DListInit(Node** head)
{
assert(head);
*head = DListCreate(0);
//next prev 都指向head
(*head)->next = *head;
(*head)->prev = *head;
}
// 双向链表头插
void DListPushFront(Node* head, DataType data)
{
//插在头节点head下一个节点的前面
DListInsert(head->next, data);
}
// 双向链表头删
void DListPopFront(Node* head)
{
assert(head);
DListErase(head->next);
}
//尾插
void DListPushBack(Node* head, DataType data)
{
//直接插在head的前面
DListInsert(head, data);
}
//尾删
void DListPopBack(Node* head)
{
assert(head);
DListErase(head->prev);
}
// 双向链表在pos的前面进行插入
void DListInsert(Node* pos, DataType data)
{
Node* newNode = NULL;
if (NULL == pos