数据结构之单链表的基本实现

在数据结构的学习中,链表可以说是我们最早接触到的一种数据结构了(字符串和数组除外),在各大数据结构及算法书中,如CLRS,或者是清华大学版数据结构中,链表也是最早介绍的一种数据结构。它实现起来比较简单,同时能实现一些我们平时用数组难以实现的功能,很适合我们入手数据结构。下面我们简单来看看链表中最简单的一种,单链表的结构及其实现。

链表是一种线性的数据结构,它由结点构成,每个结点由数据域和指针域组成。其中,除了头结点外和尾结点外,每个结点都有一个前驱及后继。其中结点的数据域储存数据,指针则指向后继结点。如图所示
单链表结构

链表相对于数组,它的有点在于能够快速地增加或者删除元素,只需要改变指针指向,无需移动元素。其增加元素删除元素的时间复杂度是O(1),而数组的时间复杂度为O(n)。另外,链表相比之于数组其劣势在于无法随机访问元素,若要访问链表中的某一位置的元素,必须从表头开始遍历,时间复杂度为O(n),相比之下数组可以通过下标直接索引,时间复杂度仅为O(n)。另外,由于每个链表结点中,既储存了数据,又储存了指针,所以链表的存储密度小于1。(存储密度 = (结点数据本身所占的存储量)/(结点结构所占的存储总量))

下面是简单的单链表的c++源代码实现:

首先是LinkList.h的头文件,其定义了链表支持的方法。

using namespace std;
struct ListNode
{
    int  val;           //数据域
    ListNode *next;     //指针域
    ListNode(int x) :val(x), next(NULL){}
};
class List
{
private:
    ListNode* head;
    int len;
public :
    List();                     //构造函数
    ~List();                   //析构函数
    int length();               //返回链表长度
    void display();             //输出链表
    void push_back(int val);            //在链表末尾插入新元素
    void insert(int val, int pos);      //在链表指定位置插入新元素
    bool empty();           //判断链表是否为空
    void erase(int pos);        //删除指定位置的元素
    bool search(int val);       //查询值为val的元素
};

接下来是cpp文件,是链表方法的实现:

// List_1.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "LinkList.h"
#include <iostream>
using namespace std;
//链表构造函数
List::List()
{
    head = NULL;
    len = 0;
}
//链表的析构函数,遍历链表并且删除每个结点
List::~List()
{
    ListNode *p = NULL;
    if (head)
    {
        p = head;
        while (len)
        {
            head = p->next;
            delete p;
            p = head;
            --len;
        }
    }
}
//返回链表长度
int List::length()
{
    return len;
}
//判断链表是否为空
bool List::empty()
{
    return len == 0;
}
//链表末尾插入。
void List::push_back(int val)
{
    //若链表为空,则需要生成一个头结点
    if (head == NULL)
        head = new ListNode(val);
    else 
    {
        ListNode *p = head;
        while (p->next)
            p = p->next;
        p->next = new ListNode(val);
    }
    ++len;
}
void List::display()
{
    ListNode *p = head;
    while (p)
    {
        cout << p->val << " ";
        p = p->next;
    }
    cout << endl;
    delete p;
}
//在第pos位插入一个新的元素
void List::insert(int val, int pos)
{
    //插入位置必须为1到len+1范围内
    if (pos > len + 1||pos<1)
    {
        cout << "超出链表范围" << endl;
        return;
    }
    //若在链表头部插入,则需要更改头结点
    else if (pos == 1)
    {
        ListNode *s = new ListNode(val);
        s->next = head;
        head = s;
        ++len;
        return;
    }
    ListNode *p = head;
    for (int i = 0; i < pos - 2; ++i)
        p = p->next;
    ListNode *s = new ListNode(val);
    s->next = p->next;
    p->next = s;
    ++len;
}
//判断一个元素是否在链表内
bool List::search(int val)
{
    ListNode *p = head;
    while (p)
    {
        if (p->val == val)
            return true;
        p = p->next;
    }
    delete p;
    return false;
}
//删除pos位的元素
void List::erase(int pos)
{
    //删除元素的位置必须大于0且小于等于链表长度
    if (pos > len||pos<1)
    {
        cout << "超出范围" << endl;
        return;
    }
    //若在顶端删除,则需要更改头结点
    else if (pos == 1)
    {
        ListNode *s = head;
        head = s->next;
        delete s;
        --len;
        return;
    }
    //链表中间删除
    ListNode *p = head;
    for (int i = 0; i < pos - 2; ++i)
        p = p->next;
    ListNode *s = p->next;
    p->next = s -> next;
    delete s;
    --len;
}
int _tmain(int argc, _TCHAR* argv[])
{
    List l = List();
    //测试插入功能
    l.insert(1,1);
    l.insert(0, 1);
    l.insert(-1, 1);
    l.display();
    //测试删除功能
    l.erase(1);
    l.display();
    //测试末尾插入
    l.push_back(1);
    l.push_back(2);
    l.push_back(3);
    l.push_back(4);
    l.display();
    //测试搜索功能
    cout << l.search(1) << endl;
    l.display();
    //测试链表长度函数
    cout << l.length() << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/h4329201/article/details/78171885