2、线性表

1、线性表基础

1.1. 概念

   是最基本,最简单和最常用的数据结构(线性表,栈,队列,串和数组都是线性结构),同时也是其他数据结构的基础。。

   线性表中各数据元素之间的关系是一对一,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的。

   是由nn要大于等于0)个数据元素(结点)组成的有限序列

   形如:A1A2A3.An这样含有有限的数据序列,我们就称之为线性表。

1.2. 特点

(1)有且仅有一个开始结点

(2)有且仅有一个终结结点

(3)内部结点都有且仅有一个直接前驱结点和一个直接后继结点

1.3. 常见操作

         定义线性表的接口,要实现这些功能:

            判断是否为空

线性表长度

GETSET方法

ADD方法

REMOVE方法

Clear方法

 

 

 

 

 

2、线性表的两种实现方式

2.1. 顺序方式

概念:用一组地址连续的存储单元依次存储线性表的数据元素,这种存储结构的线性表称为顺序表

特点:逻辑上相邻的数据元素,物理次序也是相邻的。

      他的优点是存储密度大,因为存储顺序是连续的,几乎不浪费空间

      他的缺点是插入删除等运算不方便,如在中间插入一个数据元素,那么这个数据元素之后的所有数据元素都要后移一个位置,才能重新生成一个完整的线性表。

      

 

 

 

 

 

顺序表的程序实现

 

 interface IMyLinearList

    {

        bool IsEmpty();

        bool Add(int index,Object item);

        void Clear();

        object Remove(int index);

        Object Get(int index);

        Object Set(int index, object item);

        int Size();

    }

 class MySequenceList : IMyLinearList

    {

        private object[] sList = null;

        private int size = 0;

        private int defaultCapacity = 10;

 

        public MySequenceList(int capacity)

        {

            if (capacity > 0)

            {

                sList = new object[capacity];

            }

            else

            {

                sList = new object[defaultCapacity];

            }

            size = 0;

        }

 

        bool IMyLinearList.Add(int index, object item)

        {

            /*

             * 新增思路:首先将index位置后的所有元素都后移一个位置,空出index的位置

             */

            if (index < 0 || index > size)

            {

                throw new IndexOutOfRangeException("索引越界");

            }

            if (sList.Length == size)

            {

                //重新给顺序表分配内存空间

                object[] temp = sList;

                sList = new object[sList.Length * 2];

                for (int i = 0; i < temp.Length; i++)

                {

                    sList[i] = temp[i];

                }

            }

            //将索引位置为index后面的所有元素都后移一位,目的是给新插入的值留位置

            for (int j = size - 1; j >= index; j--)

            {

                sList[j + 1] = sList[j];

            }

            //后移完毕,添加新的值

            sList[index] = item;

            size++;

            return true;

        }

 

        void IMyLinearList.Clear()

        {

            for (int i = 0; i < size; i++)

            {

                sList[i] = null;

            }

            size = 0;

        }

 

        object IMyLinearList.Get(int index)

        {

            RangeCheck(index);

            return sList[index];

        }

 

        object IMyLinearList.Set(int index, object item)

        {

            RangeCheck(index);

            object oldValue = sList[index];

            sList[index] = item;

            return oldValue;

        }

 

        bool IMyLinearList.IsEmpty()

        {

            return size == 0;

        }

 

        object IMyLinearList.Remove(int index)

        {

            //删除数据,后面的数据元素前移一位

            RangeCheck(index);

            object oldValue = sList[index];

            for (int i = index; i < size - 1; i++)

            {

                sList[i] = sList[i + 1];

            }

            sList[size - 1] = null;

            size--;

            return oldValue;

        }

 

 

 

        int IMyLinearList.Size()

        {

            return size;

        }

 

 

        private void RangeCheck(int index)

        {

            if (index < 0 || index >= size)

            {

                throw new IndexOutOfRangeException("索引越界");

            }

        }

    }

 

 

 

运行:

 

IMyLinearList lineList = new MySequenceList(20);

 

            //lineList.Add(-1,90); //抛出异常,索引越界

            lineList.Add(0,35);

            lineList.Add(1, 20);

            lineList.Add(2, 66);

            lineList.Add(3, 87);

            lineList.Add(4, 77);

            lineList.Add(5, 99);

 

            Console.WriteLine(lineList.Get(5));

 

 

顺序表的选择排序:

    

 

 

 

class ArraySort

    {

        /// <summary>

        /// 一轮选择排序算法

        /// 原理:遍历之后剩余的元素,谁小就放到前头

        /// </summary>

        /// <param name="iList">要排序的线性表</param>

        /// <param name="placeNum">要排序的位置</param>

        /// <returns>排序一轮后的结果</returns>

        public static IMyLinearList Sort(IMyLinearList iList, int placeNum)

        {

            if (placeNum < 0 || placeNum >= iList.Size())

            {

                return iList;

            }

 

            int elment = (int)iList.Get(placeNum);//要排序的元素值

            int j = elment;//一轮排序中找到的最小元素值

            int elementIndex = placeNum;//记录将要排序的元素最终放置的位置

 

            for (int i = placeNum; i < iList.Size(); i++) //排序是从要排序的位置开始一直到线性表的结尾

            {

                if (j > (int)iList.Get(i))

                {//如果找到了 比 要排序的元素值还小的值,就需要把这个值付给j

                    j = (int)iList.Get(i);

                    elementIndex = i;//记录下位置

                }

            }

 

            //循环完毕后,替换位置

            if (elementIndex != placeNum)

            {

                iList.Set(placeNum, j);//要排序的位置 赋值值

                iList.Set(elementIndex, elment);//要替换的位置 赋新值

            }

            return iList;

        }

    }

 

 

 IMyLinearList lineList = new MySequenceList(20);

 

            //lineList.Add(-1,90); //抛出异常,索引越界

            lineList.Add(0,35);

            lineList.Add(1, 20);

            lineList.Add(2, 66);

            lineList.Add(3, 87);

            lineList.Add(4, 77);

            lineList.Add(5, 99);

 

            Console.WriteLine(lineList.Get(5));

 

 

            //选择排序

            for (int i = 0; i < lineList.Size(); i++)

            {

                ArraySort.Sort(lineList, i);

                Console.WriteLine(""+i.ToString()+"次排序的结果:");

                for (int j = 0; j < lineList.Size(); j++)

                {

                    Console.Write(lineList.Get(j)+" ");

                }

                Console.WriteLine();

            }

 

            Console.ReadKey();

 

 

 

 

 

2.2. 链式方式

 

概念:用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的),包括数据域和指针域,数据域存数据,指针域指示其后继的信息。

 

存储单元的地址是分散的,但逻辑关系是连续的。

为了表示这些数据元素是一个数据表,而且表示出数据元素之间的先后关系,因此需要在每个结点上需要一个附加信息即指针。他指向这个数据元素的后继结点的地址。

 

有三种方式:单链表、循环链表和双链表。

 

2.2.1. 单链表

也叫线性链表,是由一个个结点链接而成。单链表的结点只有一个存放数据的数据域和一个称为next的指向后继结点的指针域。

 

 

 

 

 

 

如图所示,k1next指针域存储的地址是10031003是一个内存存储地址),根据1003就可以找到k2结点,以此类推。。。

 

 

单链表的程序实现:

 

public interface IMyLinearList

    {

        bool IsEmpty();

        bool Add(int index,Object item);

        void Clear();

        object Remove(int index);

        Object Get(int index);

        Object Set(int index, object item);

        int Size();

    }

 

   /// <summary>

    /// 结点类

    /// </summary>

    class Node

    {

        /// <summary>

        /// 结点值

        /// </summary>

        public object nodeValue;

 

        /// <summary>

        /// 指向下一个结点的指针

        /// </summary>

        public Node next;

 

        public Node()

        {

            nodeValue = null;

            next = null;

        }

        public Node(object initValue)

        {

            this.nodeValue = initValue;

            this.next = null;

        }

        public Node(object initValue, Node next)

        {

            this.nodeValue = initValue;

            this.next = next;

        }

    }

 

    /// <summary>

    /// 单链表

    /// </summary>

    class SingleLinkedList : IMyLinearList

    {

        public Node Head { get; set; }

        public SingleLinkedList() { }

        public SingleLinkedList(Node head)

        {

            this.Head = head;

        }

 

        bool IMyLinearList.IsEmpty()

        {

            return Head == null;

        }

 

        bool IMyLinearList.Add(int index, object item)

        {

            IMyLinearList list = this;

            if (index < 0 || index > list.Size())

            {

                throw new IndexOutOfRangeException("索引越界");

            }

            if (Head == null)

            {

                Head = new Node(item);

            }

            else

            {

                Node p = Head;

                for (int i = 0; i < index - 1; i++)

                {

                    p = p.next;

                }

                p.next = new Node(item, p.next);

            }

            return true;

        }

 

        void IMyLinearList.Clear()

        {

            Head = null;

        }

 

        object IMyLinearList.Remove(int index)

        {

            object oldValue = null;

            if (index >= 0 && Head != null)

            {

                if (index == 0)

                {//删除头结点

                    oldValue = Head.nodeValue;

                    Head = Head.next;

                }

                else

                {//删除非头结点

                    Node p = Head;

                    for (int i = 0; i < index - 1; i++)

                    {

                        if (p.next != null)

                        {

                            p = p.next;

                        }

                    }

                    if (p.next != null)

                    {

                        oldValue = p.next.nodeValue;

                        p.next = p.next.next;

                    }

                }

            }

            return oldValue;

        }

 

        object IMyLinearList.Get(int index)

        {

            RangeCheck(index);

 

            Node p = Head;

            for (int i = 0; i < index; i++)

            {

                p = p.next;

            }

            return p.nodeValue;

        }

 

        object IMyLinearList.Set(int index, object item)

        {

            RangeCheck(index);

            Node p = Head;

            for (int i = 0; i < index; i++)

            {

                p = p.next;

            }

            object oldValue = p.nodeValue;

            p.nodeValue = item;

            return oldValue;

        }

 

        int IMyLinearList.Size()

        {

            int size = 0;

            Node p = this.Head;

            while (p != null)

            {

                size++;

                p = p.next;

            }

            return size;

        }

 

        private void RangeCheck(int index)

        {

            IMyLinearList list = this;

            if (index < 0 || index > list.Size() - 1)

            {

                throw new IndexOutOfRangeException("索引越界");

            }

        }

    }

 

 

调用:

 

 IMyLinearList list = new SingleLinkedList();

            list.Add(0, 10);

            //list.Add(10,33); //索引越界

 

 

            Console.WriteLine(list.Get(0));

 

            Console.Read();

 

2.2.2. 循环链表

      他在单链表的基础上,将表尾结点的指针指向了表头结点,形成了环状结构。

 

 

 

 

2.2.3. 双链表

双链表是可以同时在向前和向后两个方向上查找数据元素的单链表。她的结点除了数据域之外,还有previousnext两个指针域,分别指向直接前趋结点和直接后继结点。

 

 

posted on 2019-08-30 14:36  拭不去の泪痕  阅读(254)  评论(0编辑  收藏  举报

导航