链表简介
链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:
- 单向、双向。
- 带头、不带头。
- 循环、非循环。
单向不带头非循环链表的模拟实现
C语言版
#pragma once
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
/*---元素类型---*/
typedef int ElementType;
/*---单链表结点---*/
typedef struct Node {
/*---结点内保存的数据---*/
ElementType _data;
/*---指向下一个结点---*/
struct Node* _next;
} Node;
/*---无头单向不循环链表---*/
typedef struct SList{
/*---保存第一个结点指针---*/
Node* _first;
} SList;
/*---初始化---*/
void SLInit(SList* sl){
assert(sl != NULL);
/*---链表为空---*/
sl->_first = NULL;
}
/*---释放---*/
void SLDestroy(SList* sl){
assert(sl != NULL);
/*---链表为空---*/
if (sl->_first == NULL){
return;
}
/*---当前结点不为空---*/
while (sl->_first != NULL){
/*---保存要释放的结点---*/
Node* temp = sl->_first;
/*---向后走一个位置---*/
sl->_first = sl->_first->_next;
/*---释放结点---*/
free(temp);
}
}
/*---创建新结点---*/
Node* CreateNode(ElementType e){
Node* node = (Node*)malloc(sizeof(Node));
node->_data = e;
node->_next = NULL;
return node;
}
/*---头插---*/
void SLPushFront(SList* sl, ElementType e){
assert(sl != NULL);
/*---创建新结点---*/
Node* node = CreateNode(e);
/*---新结点指向原链表中第一个结点---*/
node->_next = sl->_first;
/*---新结点成为链表中第一个结点---*/
sl->_first = node;
}
/*---头删---*/
void SLPopFront(SList* sl){
assert(sl != NULL);
/*---第一个结点为空---*/
if (sl->_first == NULL){
return;
}
else{
/*---保存要释放的结点---*/
Node* temp = sl->_first;
/*---向后走一个位置---*/
sl->_first = sl->_first->_next;
/*---释放第一个结点---*/
free(temp);
}
}
/*---尾插---*/
void SLPushBack(SList* sl, ElementType e){
assert(sl != NULL);
/*---创建新结点---*/
Node* node = CreateNode(e);
/*---链表为空---*/
if (sl->_first == NULL){
sl->_first = node;
}
/*---链表不为空---*/
else{
/*---保存当前结点---*/
Node* cur = sl->_first;
/*---如果当前结点的下一个不为空---*/
while (cur->_next != NULL){
/*---向后走---*/
cur = cur->_next;
}
/*---cur为当前结点的下一个结点---*/
cur->_next = node;
}
}
/*---尾删---*/
void SLPopBack(SList* sl){
assert(sl != NULL);
/*---链表为空---*/
if (sl->_first == NULL){
return;
}
/*---链表只有一个结点---*/
else if (sl->_first->_next == NULL){
free(sl->_first);
sl->_first = NULL;
}
/*---链表有多个结点---*/
else{
/*---保存当前结点---*/
Node* cur = sl->_first;
/*---当前结点的下下一个结点不为空---*/
while (cur->_next->_next != NULL){
cur = cur->_next;
}
/*---此时cur为倒数第二个结点---*/
/*---保存最后一个结点的指针---*/
Node* temp = cur->_next;
cur->_next = NULL;
free(temp);
}
}
/*---查找---*/
Node* SLFind(const SList* sl, ElementType e){
assert(sl != NULL);
/*---链表为空---*/
if (sl->_first == NULL){
return NULL;
}
/*---遍历查找---*/
for (Node* cur = sl->_first; cur != NULL; cur = cur->_next){
if (cur->_data == e){
return cur;
}
}
return NULL;
}
/*---pos后插---*/
void SLInsertAfter(Node* pos, ElementType e){
/*---pos为空,直接返回---*/
if (pos == NULL){
return;
}
/*---创建新结点---*/
Node* node = CreateNode(e);
/*---新结点指向pos的下一个结点---*/
node->_next = pos->_next;
/*---pos指向新结点---*/
pos->_next = node;
}
/*---pos后删---*/
void SLEraseAfter(Node* pos){
/*---pos或pos的下一个位置为空,直接返回---*/
if (pos == NULL || pos->_next == NULL){
return;
}
/*---保存要删除结点的指针---*/
Node* temp = pos->_next;
/*---pos指向下下一个结点---*/
pos->_next = pos->_next->_next;
free(temp);
}
/*---移除e---*/
void SLRemove(SList* sl, ElementType e){
if (sl == NULL){
return;
}
/*---链表为空---*/
if (sl->_first == NULL){
return;
}
/*---第一个元素为e---*/
if (sl->_first->_data == e){
/*---保存要移除的元素---*/
Node* temp = sl->_first;
/*---将链表指向第二个元素---*/
sl->_first = sl->_first->_next;
free(temp);
return;
}
/*---链表只有一个元素---*/
if (sl->_first->_next == NULL){
return;
}
/*---链表有两个或两个以上元素---*/
Node* cur = sl->_first;
while (cur->_next != NULL){
/*---是e---*/
if (cur->_next->_data == e){
/*---保存要移除的元素---*/
Node* temp = cur->_next;
cur->_next = cur->_next->_next;
free(temp);
temp = NULL;
return;
}
else{
cur = cur->_next;
}
}
}
/*---移除全部e---*/
void SLRemoveAll(SList* sl, ElementType e){
if (sl == NULL){
return;
}
/*---链表为空---*/
if (sl->_first == NULL){
return;
}
/*---链表只有一个元素---*/
if (sl->_first->_next == NULL){
/*---为e---*/
if (sl->_first->_data == e){
free(sl->_first);
sl->_first = NULL;
}
return;
}
/*---链表有两个或两个以上元素---*/
Node* cur = sl->_first;
while (cur->_next != NULL){
/*---为e---*/
if (cur->_next->_data == e){
/*---保存要移除的元素---*/
Node* temp = cur->_next;
cur->_next = cur->_next->_next;
free(temp);
temp = NULL;
}
else{
cur = cur->_next;
}
}
/*---判断第一个元素是否为e---*/
if (sl->_first->_data == e){
/*---保存要移除的元素---*/
Node* temp = sl->_first;
sl->_first = sl->_first->_next;
free(temp);
}
}
/*---链表打印---*/
void SLDisplay(const SList* sl){
assert(sl != NULL);
/*---保存当前结点---*/
Node* cur = sl->_first;
printf("The Single Linked List is Below: \n");
/*---当前结点不为空---*/
while (cur != NULL){
printf("%d ", cur->_data);
/*---向后走---*/
cur = cur->_next;
}
printf("\n");
}
Java版
public class LinkedList {
private ListNode head = null;
// 删除所有等于指定值的结点
public void removeAll(int toRemove) {
ListNode dummyNode = new ListNode(-1);
ListNode tailNode = dummyNode;
for (ListNode curNode = this.head; curNode != null; curNode = curNode.next) {
if (curNode.val != toRemove) {
tailNode.next = curNode;
tailNode = curNode;
}
}
tailNode.next = null;
this.head = dummyNode.next;
}
// 删除指定结点
public void remove(int toRemove) {
if (this.head == null) {
return;
}
if (this.head.val == toRemove) {
this.head = this.head.next;
return;
}
for (ListNode curNode = this.head; curNode.next != null; curNode = curNode.next) {
if (curNode.next.val == toRemove) {
curNode.next = curNode.next.next;
return;
}
}
}
// 是否包含
public boolean contains(int target) {
for (ListNode curNode = this.head; curNode != null; curNode = curNode.next) {
if (curNode.val == target) {
return true;
}
}
return false;
}
// 插入到指定下标
public void addIndex(int index, int val) {
int size = this.size();
if (index < 0 || index > size) {
return;
}
if (index == 0) {
this.addFirst(val);
return;
}
if (index == size) {
this.addLast(val);
return;
}
ListNode curNode = this.head;
for (int i = 0; i < index - 1; ++i) {
curNode = curNode.next;
}
ListNode newNode = new ListNode(val);
newNode.next = curNode.next;
curNode.next = newNode;
}
// 尾插
public void addLast(int val) {
if (this.head == null) {
this.addFirst(val);
return;
}
ListNode newNode = new ListNode(val);
ListNode curNode = this.head;
while (curNode.next != null) {
curNode = curNode.next;
}
curNode.next = newNode;
}
// 头插
public void addFirst(int val) {
ListNode newNode = new ListNode(val);
newNode.next = this.head;
this.head = newNode;
}
// 清空链表
public void clear() {
this.head = null;
}
// 结点数量
public int size() {
int size = 0;
for (ListNode curNode = this.head; curNode != null; curNode = curNode.next) {
++size;
}
return size;
}
// 打印所有结点
public void display() {
System.out.print("[");
for (ListNode curNode = this.head; curNode != null; curNode = curNode.next) {
System.out.print(curNode.val);
if (curNode.next == null) {
break;
}
System.out.print(", ");
}
System.out.println("]");
}
}
class ListNode {
public int val;
public ListNode next = null;
public ListNode(int val) {
this.val = val;
}
}
双向带头循环链表模拟实现
C语言版
double_circular_linked_list.h
#pragma once
typedef int ElementType;
/*---结点---*/
typedef struct Node
{
ElementType value;
struct Node* next;
struct Node* prev;
} Node;
/*---初始化---*/
void dcllInit(Node** head);
/*---释放---*/
void dcllDestory(Node** head);
/*---头插---*/
void dcllPushFront(Node** head, ElementType v);
/*---头删---*/
void dcllPopFront(Node** head);
/*---尾插---*/
void dcllPushBack(Node** head, ElementType v);
/*---尾删---*/
void dcllPopBack(Node** head);
/*---查找---*/
const Node* dcllFind(const Node** head, ElementType v);
/*---pos前插入---*/
void dcllInsertBefore(Node* pos, ElementType v);
/*---pos删除---*/
void dcllErase(Node* pos);
/*---删除---*/
void dcllRemove(Node** head, ElementType v);
/*---移除全部---*/
void dcllRemoveAll(Node** head, ElementType v);
/*---打印---*/
void dcllDisplay(const Node** head);
double_circular_linked_list.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "double_circular_linked_list.h"
void dcllInit(Node** head)
{
assert(head != NULL);
(*head)->next = *head;
(*head)->prev = *head;
}
void dcllDestory(Node** head)
{
assert(head != NULL);
while (*head != (*head)->next)
{
Node* temp = *head;
*head = (*head)->next;
free(temp);
temp = NULL;
}
free(*head);
*head = NULL;
}
static Node* createNode(ElementType v)
{
Node* node = (Node*)malloc(sizeof(Node));
assert(node != NULL);
node->value = v;
return node;
}
void dcllPushFront(Node** head, ElementType v)
{
assert(head != NULL);
Node* node = createNode(v);
node->next = (*head)->next;
node->prev = *head;
(*head)->next->prev = node;
(*head)->next = node;
}
void dcllPopFront(Node** head)
{
assert(head != NULL);
Node* temp = (*head)->next;
(*head)->next->next->prev = *head;
(*head)->next = (*head)->next->next;
free(temp);
temp = NULL;
}
void dcllPushBack(Node** head, ElementType v)
{
assert(head != NULL);
Node* node = createNode(v);
node->next = *head;
node->prev = (*head)->prev;
(*head)->prev->next = node;
(*head)->prev = node;
}
void dcllPopBack(Node** head)
{
assert(head != NULL);
Node* temp = (*head)->prev;
(*head)->prev->prev->next = *head;
(*head)->prev = (*head)->prev->prev;
}
const Node* dcllFind(const Node** head, ElementType v)
{
assert(head != NULL);
const Node* i = NULL;
for (i = (*head)->next; i != *head; i = i->next)
{
if (i->value == v)
{
return i;
}
}
return NULL;
}
void dcllInsertBefore(Node* pos, ElementType v)
{
if (pos == NULL)
{
return;
}
Node* node = createNode(v);
node->next = pos;
node->prev = pos->prev;
pos->prev->next = node;
pos->prev = node;
}
void dcllErase(Node* pos)
{
if (pos == NULL)
{
return;
}
pos->next->prev = pos->prev;
pos->prev->next = pos->next;
free(pos);
pos = NULL;
}
void dcllRemove(Node** head, ElementType v)
{
assert(head != NULL);
Node* i = NULL;
for (i = (*head)->next; i != *head; i = i->next)
{
if (i->value == v)
{
i->next->prev = i->prev;
i->prev->next = i->next;
free(i);
i = NULL;
return;
}
}
}
void dcllRemoveAll(Node** head, ElementType v)
{
assert(head != NULL);
Node* cur = (*head)->next;
while (cur != *head)
{
if (cur->value == v)
{
Node* temp = cur->next;
cur->next->prev = cur->prev;
cur->prev->next = cur->next;
free(cur);
cur = temp;
}
else
{
cur = cur->next;
}
}
}
void dcllDisplay(const Node** head)
{
assert(head != NULL);
const Node* i = NULL;
printf("The Double Circular Linked List is below: \n");
for (i = (*head)->next; i != *head; i = i->next)
{
printf("%d ", i->value);
}
printf("\n");
}
Java版
public class LinkedList {
private ListNode head;
// 删除所有指定元素
public void removeAll(int toRemove) {
for (ListNode curNode = this.head.next; curNode != this.head; curNode = curNode.next) {
if (curNode.val == toRemove) {
curNode.next.prev = curNode.prev;
curNode.prev.next = curNode.next;
}
}
}
// 删除元素
public void remove(int toRemove) {
for (ListNode curNode = this.head.next; curNode != this.head; curNode = curNode.next) {
if (curNode.val == toRemove) {
curNode.next.prev = curNode.prev;
curNode.prev.next = curNode.next;
return;
}
}
}
// 是否包含
public boolean contains(int target) {
for (ListNode curNode = this.head.next; curNode != this.head; curNode = curNode.next) {
if (curNode.val == target) {
return true;
}
}
return false;
}
// 指定下标插入
public void addIndex(int index, int val) {
int size = this.size();
if (index < 0 || index > size) {
return;
}
if (index == 0) {
this.addFirst(val);
return;
}
if (index == size) {
this.addLast(val);
return;
}
ListNode curNode = this.head;
for (int i = 0; i < index; ++i) {
curNode = curNode.next;
}
ListNode newNode = new ListNode(val);
newNode.next = curNode.next;
newNode.prev = curNode;
curNode.next.prev = newNode;
curNode.next = newNode;
}
// 尾插
public void addLast(int val) {
ListNode newNode = new ListNode(val);
newNode.next = this.head;
newNode.prev = this.head.prev;
this.head.prev.next = newNode;
this.head.prev = newNode;
}
// 头插
public void addFirst(int val) {
ListNode newNode = new ListNode(val);
newNode.next = this.head.next;
newNode.prev = this.head;
this.head.next.prev = newNode;
this.head.next = newNode;
}
// 元素数量
public int size() {
int size = 0;
for (ListNode curNode = this.head.next; curNode != this.head; curNode = curNode.next) {
++size;
}
return size;
}
// 清空
public void clear() {
this.head.next = this.head;
this.head.prev = this.head;
}
// 打印
public void display() {
System.out.print("正向: [");
for (ListNode curNode = this.head.next; curNode != this.head; curNode = curNode.next) {
System.out.print(curNode.val);
if (curNode == this.head.prev) {
break;
}
System.out.print(", ");
}
System.out.println("]");
System.out.print("反向: [");
for (ListNode curNode = this.head.prev; curNode != this.head; curNode = curNode.prev) {
System.out.print(curNode.val);
if (curNode == this.head.next) {
break;
}
System.out.print(", ");
}
System.out.println("]");
}
public LinkedList() {
this.head = new ListNode(-1);
this.head.next = this.head;
this.head.prev = this.head;
}
}
class ListNode {
public int val;
public ListNode prev = null;
public ListNode next = null;
public ListNode(int val) {
this.val = val;
}
}