数据结构(二)——线性表

一:线性表的概述

线性表是最简单最基本的一种数据结构,线性表中的数据元素都存在一对一的关系,属于线性结构,是有顺序有先后关系的,除了第一个元素外,其他数据元素前只有一个数据元素(前驱),除了最后一个元素外,其他数据元素后只有一个数据元素(后驱)


二:线性表的顺序存储结构

用一段地址连续的存储单元依次存储线性表中的数据元素

线性表的顺序存储结构在读、存数据时,时间复杂度都是O(1),我们把读、存数据时时间复杂度为O(1)的存储结构称为随机存储结构
在插入、删除数据时,时间复杂度是O(n),数组就是线性表的顺序存储结构的体现,这也是为什么数组比较适合元素个数不太变化,更多的是存取数据的应用


三:线性表的链式存储结构

引言:对于线性表的顺序存储结构,当元素个数不太变化时很适用,但是当我们插入、删除数据时,有可能会移动大量的数据,从而耗费时间,根本原因在于顺序存储结构中数据与数据之间的存储位置是连续的,当我们插入、删除数据时,也要让线性表中的数据仍然保持内存的连续,既然这样,我们可以不考虑内存的连续,只是让每个元素知道它下一个元素的地址就可以,这就是线性表的链式存储结构(链表)

为了表示ai与ai+1之间的关系,对于ai来说,除了存储本身的信息外,还需要存储一个指向它直接后继的信息(直接后继的地址),我们把存储本身数据信息的域称为数据域,把存储直接后继位置的域称为指针域,数据域与指针域组成了ai的存储映像,称为结点,n个结点组成为一个链表,也就是线性表的链式存储结构(链表)。又因为此链表中的每个结点只包含一个指针域(只能指向直接后驱),所以称为单链表

我们把线性表的链式存储结构中指向第一个结点的指针称为头指针,链表的存储从头指针开始进行,之后的每一个结点都是上一个的指针指向的地址,规定最后一个的结点的指针域为NULL,有时候为了方便操作,会在第一个结点前附设一个结点,称为头结点,头结点的数据域可以不存储任何信息(也可以存储线性表的公共数据),头结点的指针域(也就是头指针)指向第一个结点的地址,就算线性单链表为空,头指针也不能为空,但是头结点是附设的可以没有

线性表的链式存储结构对于插入、删除数据越频繁的操作优势越是明显


四:线性表的顺序存储与链式存储的比较


五:其他链表

——静态链表

引言:对于C、C++来说,它具有指针,可以方便地操作内存中的地址和数据,而对于C#、Java等面向对象的语言,虽然没有指针但是可以利用引用间接地实现指针的作用,但是对于早期的一些编程语言,例如Basic、Fortran等,由于没有指针也不是面向对象语言,所以前人就想出了用数组代替指针,我们把这种描述方式称为游标实现法,把这种用数组描述的链表称为静态链表

首先让数组中的每个元素都是由两个数据域组成,data和cur,data存储数据元素,cur存储下一个元素在数组中的下标(与单链表中的next指针作用相同),把未被使用的数组元素称为备用链表,另外对数组中的第一个和最后一个元素进行特殊处理,都不存储数据,第一个元素的cur存储第一个备用链表的下标,最后一个元素的cur存储第一个有数值的元素的下标(与头结点作用相同),当某一个元素的cur为0时,则此元素是静态链表中最后一个有数值的元素


——循环链表

引言:对于单链表,我们无法从中间某个结点开始遍历到整个链表的结点,所以引出了循环链表

将单链表中的最后一个结点由空指针改为指向头结点的指针,使整个单链表形成了一个环,这样头尾相连的单链表称为循环链表
循环链表与单链表最主要的差别就在于循环的判断条件上,单链表是判断结点的指针指向是否为空,而循环链表是判断结点的指针指向是否为头结点

——双向链表

引言:对于单链表,我们无法从某个结点访问到前驱的结点,所以引出了双向链表

将单链表的每个结点中,再设置一个指向其直接前驱的指针域,相当于每个结点有两个指针域,一个指向直接前驱,一个指向直接后驱,这样的链表称为双向链表
双向链表与单链表最主要的差别就在于插入、删除元素上,需要更改两个指针的指向


六:实现线性表的顺序存储结构(顺序表)

using System;

//顺序表类
public class LinearList<T>
{
    //存储顺序表中元素的数组
    private T[] array;

    //顺序表中元素的个数
    private int count;
    public int Count
    {
        get
        {
            return count;
        }
    }

    //构造器初始化
    public LinearList()
    {
        array = new T[0];
    }
    public LinearList(int size)
    {
        array = new T[size];
    }

    //判断顺序表是否已满
    private bool IsFull()
    {
        return count >= array.Length;
    }

    //判断索引是否正确
    private bool IndexIsVaild(int index)
    {
        return index >= 0 && index <= array.Length - 1;
    }

    //得到顺序表长度
    public int GetLength()
    {
        return count;
    }

    //清空顺序表
    public void Clear()
    {
        for (int i = 0; i < count; i++)
        {
            array[i] = default(T);
        }
        count = 0;
    }

    //添加元素
    public void AddItem(T item)
    {
        if (!IsFull())
        {
            array[count] = item;
            count++;
        }
        else
        {
            throw new Exception("表已满");
        }
    }

    //得到元素(不通过索引器)
    public T GetItem(int index)
    {
        if (IndexIsVaild(index))
        {
            return array[index];
        }
        else
        {
            throw new Exception("索引超出范围");
        }
    }
    //得到元素(通过索引器)
    public T this[int index]
    {
        get
        {
            if (IndexIsVaild(index))
            {
                return array[index];
            }
            else
            {
                throw new Exception("索引超出范围");
            }
        }
        set
        {
            if (!IsFull())
            {
                array[index] = value;
            }
            else
            {
                throw new Exception("顺序表当前已满");
            }
        }
    }

    //判断顺序表是否为空
    public bool IsEmpty()
    {
        return count == 0;
    }

    //插入元素
    public void Insert(int index, T item)
    {
        if (!IsFull() == false)
        {
            if (IndexIsVaild(index))
            {
                for (int i = count - 1; i >= index; i--)
                {
                    array[i + 1] = array[i];
                }
                array[index] = item;
                count++;
            }
            else
            {
                throw new Exception("索引超出范围");
            }
        }
        else
        {
            throw new Exception("顺序表当前已满");
        }
    }

    //移除元素(通过指定位置)
    public void RemoveAt(int index)
    {
        if (IndexIsVaild(index))
        {
            for (int i = index + 1; i < count; i++)
            {
                array[index - 1] = array[index];
            }
            count--;
        }
        else
        {
            throw new Exception("索引超出范围");
        }
    }
    //移除元素(通过指定元素)
    public void Remove(T item)
    {
        int index = 0;
        for (int i = 0; i < count; i++)
        {
            if (array[i].Equals(item))
            {
                index = i;
            }
        }
        RemoveAt(index);
    }

    //获取元素位置
    public int IndexOf(T item)
    {
        for (int i = 0; i < count; i++)
        {
            if (array[i].Equals(item))
            {
                return i;
            }
        }
        return -1;
    }
}

class Program
{
    //*****进行测试*****
    static void Main(string[] args)
    {
        LinearList<int> myList = new LinearList<int>(5);
        myList.AddItem(1);
        myList[1] = 2;
        myList.Insert(1, 3);
        myList.Remove(1);
        myList.RemoveAt(1);
    }
}

七:实现线性表的链式存储结构(单链表)

using System;

//结点类
public class Node<T>
{
    //存储数据(数据域)
    public T Data { get; set; }

    //存储下一个结点的地址(指针域)——引用
    public Node<T> Next { get; set; }

    //构造器初始化
    public Node()
    {
        this.Data = default(T);
        Next = null;
    }
    public Node(T value)
    {
        this.Data = value;
        Next = null;
    }
    public Node(T value, Node<T> next)
    {
        this.Data = value;
        this.Next = next;
    }
    public Node(Node<T> next)
    {
        this.Next = next;
    }
}

//链表类
public class LinearList<T>
{
    //头结点
    private Node<T> head;

    //链表长度
    private int length;
    public int Length
    {
        get
        {
            return length;
        }
    }

    //构造器初始化
    public LinearList()
    {
        head = null;
    }

    //得到链表长度
    public int GetLength()
    {
        return length;
    }

    //判断索引是否正确
    private bool IndexIsVaild(int index)
    {
        return index >= 0 && index <= length - 1;
    }

    //添加元素
    public void AddItem(T item)
    {
        Node<T> newNode = new Node<T>(item);
        if (head == null)
        {
            head = newNode;
        }
        else
        {
            Node<T> temp = head;
            while (true)
            {
                if (temp.Next != null)
                {
                    temp = temp.Next;
                }
                else
                {
                    break;
                }
            }
            temp.Next = newNode;
        }
        length++;
    }

    //插入元素
    public void Insert(int index, T item)
    {
        Node<T> newNode = new Node<T>(item);
        if (index == 0)
        {
            newNode.Next = head;
            head = newNode;
            length++;
        }
        else
        {
            if (IndexIsVaild(index))
            {
                Node<T> temp = head;
                for (int i = 1; i <= index - 1; i++)
                {
                    temp = temp.Next;
                }
                Node<T> preNode = temp;
                Node<T> nextNode = temp.Next;
                preNode.Next = newNode;
                newNode.Next = nextNode;
                length++;
            }
            else
            {
                throw new Exception("索引超出范围");
            }
        }
    }

    //删除元素
    public void Remove(int index)
    {
        if (IndexIsVaild(index))
        {
            if (index == 0)
            {
                head = head.Next;
            }
            else
            {
                Node<T> temp = head;
                for (int i = 1; i <= index - 1; i++)
                {
                    temp = temp.Next;
                }
                Node<T> preNode = temp;
                Node<T> nextNode = temp.Next.Next;
                preNode.Next = nextNode;
            }
            length--;
        }
        else
        {
            throw new Exception("索引超出范围");
        }
    }

    //清空链表
    public void CLear()
    {
        head = null;
    }

    //获取元素(通过索引器)
    public T this[int index]
    {
        get
        {
            if (IndexIsVaild(index))
            {
                Node<T> temp = head;
                for (int i = 1; i <= index; i++)
                {
                    temp = temp.Next;
                }
                return temp.Data;
            }
            else
            {
                throw new Exception("索引超出范围");
            }
        }
        set
        {
            if (IndexIsVaild(index))
            {
                Node<T> newNode = new Node<T>(value);
                Node<T> temp = head;
                for (int i = 1; i <= index - 1; i++)
                {
                    temp = temp.Next;
                }
                Node<T> preNode = temp;
                Node<T> nextNode = temp.Next.Next;
                preNode.Next = newNode;
                newNode.Next = nextNode;
            }
            else
            {
                throw new Exception("索引超出范围");
            }
        }
    }
    //获取元素(不通过索引器)
    public T GetItem(int index)
    {
        if (IndexIsVaild(index))
        {
            Node<T> temp = head;
            for (int i = 1; i < index; i++)
            {
                temp = temp.Next;
            }
            return temp.Data;
        }
        else
        {
            throw new Exception("索引超出范围");
        }
    }

    //获取元素位置
    public int IndexOf(T item)
    {
        int index = 0;
        Node<T> temp = head;
        while (true)
        {
            if (temp.Data.Equals(item))
            {
                return index;
            }
            else
            {
                if (temp.Next != null)
                {
                    temp = temp.Next;
                    index++;
                }
                else
                {
                    break;
                }
            }
        }
        return -1;
    }

    //判断链表是否为空
    public bool IsEmpty()
    {
        return length == 0 || head == null;
    }
}

class Program
{
    //*****进行测试*****
    public static void Main(string[] args)
    {
        LinearList<int> myList = new LinearList<int>();
        myList.AddItem(1);
        myList.AddItem(2);
        myList[1] = 3;
        myList.Insert(1, 4);
        myList.Remove(2);
    }
}
发布了127 篇原创文章 · 获赞 278 · 访问量 24万+

猜你喜欢

转载自blog.csdn.net/LLLLL__/article/details/100606235
今日推荐