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

来源:互联网 发布:油性皮肤洗面奶知乎 编辑:程序博客网 时间:2024/06/05 02:39

在数据结构的学习中,链表可以说是我们最早接触到的一种数据结构了(字符串和数组除外),在各大数据结构及算法书中,如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;}
原创粉丝点击