『数据结构』链表

链表简介


链表是一种物理存储结构上非连续、非顺序的存储结构数据元素的逻辑顺序是通过链表中的指针链接次序实现的
实际中链表的结构非常多样,以下情况组合起来就有8种链表结构

  1. 单向、双向
  2. 带头、不带头
  3. 循环、非循环

单向不带头非循环链表的模拟实现


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;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值