数据结构经典面试之链表——C#和C++篇


在这里插入图片描述

链表是一种常见的基础数据结构,它由一系列节点组成,每个节点包含数据域和指向下一个节点的指针。链表与数组不同,它不要求节点在内存中连续存储,这使得链表在插入和删除操作时具有较高的效率。

本文将介绍链表的基本概念、操作以及在C#和C++语言中的实现。

一、链表的基本概念

节点(Node)
节点是链表的基本单元,它包含两个部分:数据域和指针域。数据域用于存储节点的数据,指针域用于存储下一个节点的地址。

单链表(Singly Linked List)
单链表是一种每个节点只有一个指针指向下一个节点的链表。它是链表的最基本形式。

双向链表(Doubly Linked List)
双向链表是一种每个节点有两个指针,一个指向前一个节点,另一个指向下一个节点的链表。这使得双向链表可以方便地访问节点的前驱和后继。

循环链表(Circular Linked List)
循环链表是一种最后一个节点的指针指向第一个节点的链表。这使得循环链表在末尾追加节点时更为方便。

二、链表的操作

  • 插入操作

插入操作包括在链表的头部、中间和尾部插入节点。

(1)在链表头部插入节点

在链表头部插入节点时,新节点的指针指向原头节点,然后将新节点设置为头节点。

(2)在链表中间插入节点

在链表中间插入节点时,需要找到插入位置的前一个节点,将新节点的指针指向原中间节点,然后将原中间节点的指针指向新节点。

(3)在链表尾部插入节点

在链表尾部插入节点时,需要找到链表的最后一个节点,将最后一个节点的指针指向新节点,然后将新节点设置为最后一个节点。

  • 删除操作

删除操作包括删除链表的头部、中间和尾部节点。

(1)删除链表头部节点

删除链表头部节点时,需要将头节点的指针指向下一个节点,然后将原头节点从链表中释放。

(2)删除链表中间节点

删除链表中间节点时,需要找到删除节点的前一个节点,将前一个节点的指针指向删除节点的下一个节点。

(3)删除链表尾部节点

删除链表尾部节点时,需要找到链表的最后一个节点的前一个节点,将最后一个节点的前一个节点的指针指向null。

三、定义链表的节点结构体(C#)

在C#中,我们首先定义链表的节点结构体,它包含数据域和指向下一个节点的指针。

public struct Node
{
    public int Data { get; set; }
    public Node Next { get; set; }

    public Node(int data)
    {
        Data = data;
        Next = null;
    }
}

四、定义链表的基本操作类(C#)

在C#中,我们定义一个链表类,包含基本操作方法,如插入、删除等。

public class LinkedList
{
    public Node Head { get; set; }

    public void InsertAtHead(int data)
    {
        var newNode = new Node(data);
        newNode.Next = Head;
        Head = newNode;
    }

    public void InsertAtTail(int data)
    {
        var newNode = new Node(data);
        if (Head == null)
        {
            Head = newNode;
            return;
        }

        var current = Head;
        while (current.Next != null)
        {
            current = current.Next;
        }

        current.Next = newNode;
    }

    public void DeleteAtHead()
    {
        if (Head == null)
        {
            return;
        }

        Head = Head.Next;
    }

    public void DeleteAtTail()
    {
        if (Head == null)
        {
            return;
        }

        if (Head.Next == null)
        {
            Head = null;
            return;
        }

        var current = Head;
        while (current.Next.Next != null)
        {
            current = current.Next;
        }

        current.Next = null;
    }
}

五、创建一个链表实例并进行基本操作演示(C#)

下面我们创建一个链表实例,并演示如何进行基本操作。

public class Program
{
    public static void Main(string[] args)
    {
        LinkedList linkedList = new LinkedList();

        linkedList.InsertAtHead(1);
        linkedList.InsertAtHead(2);
        linkedList.InsertAtHead(3);
        linkedList.InsertAtTail(4);

        linkedList.DeleteAtHead();
        linkedList.DeleteAtTail();
    }
}

六、编写一个自定义链表操作函数(C++)

在C++中,我们首先定义链表的节点结构体,然后编写一个自定义链表操作函数,用于创建和打印链表。

#include <iostream>

struct Node
{
    int data;
    Node *next;

    Node(int data) : data(data), next(nullptr) {}
};

void printList(Node *head)
{
    Node *current = head;
    while (current != nullptr)
    {
        std::cout << current->data << " -> ";
        current = current->next;
    }
    std::cout << "null" << std::endl;
}

Node* createList(int arr[], int n) {
    Node* dummy = new Node(0);
    Node* tail = dummy;
    for (int i = 0; i < n; ++i) {
        Node* newNode = new Node(arr[i]);
        tail->next = newNode;
        tail = newNode;
    }
    return dummy->next;
}

七、在C++中演示创建和操作一个链表实例(C++)

下面我们在C++中演示如何创建和操作一个链表实例。

int main()
{
    int arr[] = {1, 2, 3, 4, 5};
    int n = sizeof(arr) / sizeof(arr[0]);

    Node* head = createList(arr, n);
    printList(head);

    // 删除链表的第一个节点
    Node* temp = head;
    head = head->next;
    delete temp;

    // 插入一个新节点到链表尾部
    Node* newNode = new Node(6);
    newNode->next = nullptr;
    temp = head;
    while (temp->next != nullptr)
    {
        temp = temp->next;
    }
    temp->next = newNode;

    printList(head);

    return 0;
}

八、总结并对比C#和C++实现链表数据结构的不同点

在C#中,我们使用结构体Node和类LinkedList来实现链表。C#是一种强类型语言,它提供了自动垃圾回收机制,这使得内存管理相对简单。在C#中,我们通过属性来访问和设置节点的Data和Next字段。

在C++中,我们使用结构体Node来实现链表节点,并使用指针来访问和设置节点的data和next字段。C++是一种静态类型语言,它不提供自动垃圾回收,因此我们需要手动管理内存,例如使用new和delete操作符。

在C#中,我们直接在LinkedList类中提供了基本操作方法,如InsertAtHead、InsertAtTail、DeleteAtHead和DeleteAtTail。而在C++中,我们定义了一个createList函数来创建链表,并使用printList函数来打印链表。

总结

总的来说,C#和C++实现链表的方式有一些不同,主要体现在内存管理、类型系统和编程习惯上。然而,无论是C#还是C++,链表的核心概念和基本操作都是相似的。通过理解和掌握链表的数据结构,我们可以更加高效地处理数据和优化程序性能。

  • 19
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白话Learning

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值