线性表的链式存储结构_单向链表[带头结点]_C#实现

[参考文献: 1.严蔚敏.数据结构(C语言版) ; 2.陈广.数据结构(C#语言描述) ;3.Michael McMillan.Data Structures and Algorithms Using C#]

1.线性表的链式存储结构:

     用一组任意的存储单元(不要求地址连续)来存储线性表的元素,每个元素对应一组存储单元(称为结点),每个结点包括两个域: 存储数据元素信息的数据域和存储直

      接后继所在位置的指针域.

    . N个结点通过指针域组成的表, 称为线性链表(单链表).

    . 线性链表最后一个结点的指针域为"空” (NULL 或 ^);

    . 用一个头指针指示链表中第一个结点的存储位置;

    . 链表L = (a1 ,a2 , ……an ) 逻辑表示为 :

             L -> a1 -> a2->    -> an^

                空表时: L = NULL .

2.带头结点的链表:

    在线性链表的第一个元素结点之前附设一个结点(称头结点), 它的数据域不存储任何信息,其指针域存储第一个元素结点的存储位置. 头指针L指向该头结点.

    空表时: L->next = NULL

    带头结点链表的引入是为了使算法判空和处理一致. (空表包含头结点)

3.线性表链式存储结构的特点:

   (1) 逻辑上相邻的元素, 其物理位置不一定相邻; 元素之间的邻接关系由指针域指示.

   (2) 链表是非随机存取存储结构; 对链表的存取必须从头指针开始; 链表结点只能顺序访问,随机访问性能不佳.

   (3) 链表是一种动态存储结构; 链表的结点可调用new() 申请和dispose()释放[当然C#中是通过垃圾回收器管理内存的].

   (4) 插入删除运算非常方便; 只需修改相应指针值.

以下是用C#实现的一个单链表类:

using System;
namespace LinkedList
{

    public class LinkedList
    {
        //成员
        private int count;                                 //记录元素个数, 表长, 初始值为0
        private Node head;

        //属性
        public int Count                                   //单链表中的元素个数
        {
            get { return count; }
        }
        //索引器
        public object this[int index]
        {
            get { return Get(index).item; }
            set { Get(index).item = value; }
        }

        //方法
       
        //构造器
        public LinkedList()                                //构造带有头结点的单链表
        {
            head = new Node("头结点");
        }

        private Node Get(int index)                  //查找指定索引的元素:[1 <= index <= 表长 ]
        {
            int j = 1;
            Node p = this.head.next;                //初始化,p指向第一个结点,j为计数器
            while ((p != null) && (j < index))      //寻找第index个结点.[出循环的条件是:(1)p==null: 空表 OR index>表长 ; AND (2)j == index:已定位在第index个结点 ]
            {
                p = p.next;
                ++j;
            }
            if ((p == null) || (j > index))
            {
                //Console.WriteLine("空表或i小于1或者大于表长");
                //Console.ReadLine();
                //System.Environment.Exit(0);   
                throw new ArgumentOutOfRangeException("空表或i小于1或者大于表长");
                   
            }
            else                                           //***[条件: p != null AND j==index ]
            {
                return p;
            }

            //if ((p != null) && (j == index))             //还可以这样写!
            //{
            //    return p;
            //}
            //else
            //{
            //    throw new ArgumentOutOfRangeException("空表或i小于1或者大于表长");
            //}

        }
        public void Add(object value)                      //在链表的结尾添加元素
        {
            Node p = new Node(value);
            if (this.head.next == null)                    //如果是空表,直接在头结点后插入
            {
                head.next = p;
            }
            else
            {
                Get(count).next = p;
            }

            count++;
        }

        public void Insert(int index, object value)        //在指定索引处之前插入元素: [1 <= index <= 表长+1 ]
        {
            int j = 0;
            Node p = this.head;                            //初始化,p指向头结点,j为计数器
            while ((p != null) && (j < (index - 1)))   //寻找第index - 1个结点.[出循环的条件是:(1)p==null: index>表长+1 ; AND (2)j == index-1:已定位在index的前一个结点 ]
            {
                p = p.next;
                ++j;
            }
            if ((p == null) || (j > (index - 1)))    //index小于1或者大于表长加1   [ERROR返回条件:(1)p==null: index>表长+1 ; OR (2)j>(index-1): index位置 < 1 ]
            {
                throw new ArgumentOutOfRangeException("i小于1或者大于表长加1");
            }
            else                                           //***[条件: p != null AND j==index-1 ]
            {
                Node s = new Node(value);                  //生成新结点 
                s.next = p.next;                           //插入
                p.next = s;

                count++;                                   //表长+1

            }
        }

        public void Delete(int index)                      //删除指定索引元素 : [1 <= index <= 表长 ]
        {
            int j = 0;
            Node p = this.head;                            //初始化,p指向头结点,j为计数器
            while ((p.next != null) && (j < (index - 1))) //寻找第index - 1个结点.[出循环的条件是:(1)p.next==null: index>表长 ;(2)j == index-1:已定位在index的前一个结点 ]
            {
                p = p.next;
                ++j;
            }
            if ((p.next == null) || (j > (index - 1)))  //index小于1或者大于表长   [ERROR返回条件:(1)p.next==null: index>表长 ; OR (2)j>(index-1): index位置 < 1 ]
            {
                throw new ArgumentOutOfRangeException("i小于1或者大于表长");
            }
            else                                           //***[条件: p.next != null AND j==index-1 ]
            {
                p.next = p.next.next;                      //删除

                count--;                                   //表长-1
            }
        }

        public override string ToString()                  //打印整个链表
        {
            string s = string.Empty;
            for (Node p = head.next ; p != null; p = p.next)
            {
                s += p.item.ToString() + "  ";
            }
            return s;
       
        }
        private  class Node         //结点类
        {
            public object item;   //数据域
            public Node next;     //指针域

            public Node()
            {
                item = null;
                next = null;
            }
            public Node(object value)
            {
                item = value;
                next = null;
            }
        }


    }
}

你可能感兴趣的:(线性表)