代码改变世界

线性表 - 双链表

2011-08-13 16:26  DylanChan  阅读(221)  评论(0编辑  收藏  举报

双向链表(double linked list):在单链表的每个结点中,再设置一个指向其前驱结点的指针域

01    /// <summary>
02    /// 定义双向链表结点类
03    /// </summary>
04    public sealed class DoubleLinkedListNode<t>
05    {
06        //存放数据
07        private T tData;
08        //后继结点
09        private DoubleLinkedListNode<t> nNext;
10        //前继结点
11        private DoubleLinkedListNode<t> nPrev;
12 
13        public T Data
14        {
15            get { return this.tData; }
16            set { this.tData = value; }
17        }
18        public DoubleLinkedListNode<t> Next
19        {
20            get { return this.nNext; }
21            set { nNext = value; }
22        }
23        public DoubleLinkedListNode<t> Prev
24        {
25            get { return this.nPrev; }
26            set { nPrev = value; }
27        }
28 
29        public DoubleLinkedListNode(T data, DoubleLinkedListNode<t> next, DoubleLinkedListNode<t> prev)
30        {
31            this.tData = data;
32            this.nNext = next;
33            this.nPrev = prev;
34        }
35 
36        public DoubleLinkedListNode()
37            : this(default(T), null, null)
38        { }
39 
40        public DoubleLinkedListNode(T data)
41            : this(data, null, null)
42        { }
43    }
001    /// <summary>
002    /// 定义双向链表类(带头结点)
003    /// </summary>
004    public sealed class DoubleLinkedList<t>
005    {
006        //定义头结点
007        private DoubleLinkedListNode<t> nHead;
008        public DoubleLinkedListNode<t> Head
009        {
010            get { return this.nHead; }
011            set { nHead = value; }
012        }
013 
014        /// <summary>
015        /// 初始化带头结点的空表
016        /// </summary>
017        public DoubleLinkedList()
018        {
019            this.nHead = new DoubleLinkedListNode<t>();
020        }
021 
022        /// <summary>
023        /// 实现索引
024        /// </summary>
025        public T this[int index]
026        {
027            get { return GetElement(index + 1); }
028        }
029 
030        /// <summary>
031        /// 获取链表长度
032        /// </summary>
033        /// <returns>返回表长</returns>
034        public int Count()
035        {
036            int result = 0;
037            //指向头结点
038            DoubleLinkedListNode<t> listNode = this.nHead;
039            while (listNode.Next != null)
040            {
041                result++;
042                //移动指针,指向下一结点
043                listNode = listNode.Next;
044            }
045            return result;
046        }
047 
048        /// <summary>
049        /// 判断链表是否为空
050        /// </summary>
051        /// <returns>true, 链表为空</returns>
052        public bool IsEmpty()
053        {
054            return this.nHead.Next == null;
055        }
056 
057        /// <summary>
058        /// 清空链表
059        /// </summary>
060        public void Clear()
061        {
062            //第一结点设为NUll,所有后继结点由于失去引用,等待GC自动回收
063            this.nHead.Next = null;
064        }
065 
066        /// <summary>
067        /// 获取指定位置的元素
068        /// </summary>
069        /// <param name="i">链表位置
070        /// <returns>返回链表的元素</returns>
071        public T GetElement(int i)
072        {
073            //链表为空
074            if (IsEmpty())
075            {
076                Console.WriteLine("This Linear List Is Empty!");
077                return default(T);
078            }
079            if (i < 1 && i > this.Count())
080            {
081                Console.WriteLine("This Location Is Error!");
082                return default(T);
083            }
084            //指向头结点
085            DoubleLinkedListNode<t> listNode = this.nHead;
086            int j = 1;
087            while (j <= i)
088            {
089                //移动节点,指向下一结点
090                listNode = listNode.Next;
091                j++;
092            }
093            //获取数据
094            return listNode.Data;
095        }
096 
097        /// <summary>
098        /// 获取指定元素的位置
099        /// </summary>
100        /// <param name="item">指定元素
101        /// <returns>返回链表位置</returns>
102        public int LocateElement(T item)
103        {
104            if (IsEmpty())
105            {
106                Console.WriteLine("Linear List Is Empty!");
107                return 0;
108            }
109            int result = 0;
110            //指向头结点
111            DoubleLinkedListNode<t> listNode = this.nHead;
112            //遍历双向链表,指针指向表尾,循环结束
113            while (listNode.Next != null)
114            {
115                result++;
116                //比较链表元素与指定元素是否相等
117                if (listNode.Next.Data.Equals(item))
118                {
119                    return result;
120                }
121                //移动指针,指向下一结点
122                listNode = listNode.Next;
123            }
124            return 0;
125        }
126 
127    }

插入操作

   ◆  链表创建
   ◆  指定元素后面插入新元素
   ◆  指定元素前面插入新元素

 

 

001        /// <summary>
002        /// 以“头插法”创建双向链表
003        /// </summary>
004        /// <param name="item">待插入元素
005        public void CreateListHead(T item)
006        {
007            //待插入结点
008            DoubleLinkedListNode<t> firstNode = new DoubleLinkedListNode<t>(item);
009            //链表为空
010            if (this.nHead.Next == null)
011            {
012                //新结点作为第一结点
013                this.nHead.Next = firstNode;
014                //新结点的前继结点指向头结点
015                firstNode.Prev = this.Head;
016            }
017            else
018            {
019                //指向头结点
020                DoubleLinkedListNode<t> listNode = this.nHead;
021                //新结点的前继结点指向头结点
022                firstNode.Prev = listNode;
023                //原第一结点作为新结点的后继结点
024                firstNode.Next = listNode.Next;
025                //新结点作为原第一结点的前继结点
026                listNode.Next.Prev = firstNode;
027                //新结点作为头结点的后继结点
028                listNode.Next = firstNode;
029            }
030        }
031 
032        /// <summary>
033        /// 以“尾插法”创建双向链表
034        /// </summary>
035        /// <param name="item">侍插入元素
036        public void CreateListTail(T item)
037        {
038            //待插入结点
039            DoubleLinkedListNode<t> lastNode = new DoubleLinkedListNode<t>(item);
040            if (this.nHead.Next == null)
041            {
042                //新结点作为第一结点
043                this.nHead.Next = lastNode;
044                //新结点的前继结点指向头结点
045                lastNode.Prev = this.nHead;
046                return;
047            }
048            //指向头结点
049            DoubleLinkedListNode<t> listNode = this.nHead;
050            //遍历到表尾结点
051            while (listNode.Next != null)
052            {
053                //移动指针,指向下一结点
054                listNode = listNode.Next;
055            }
056            //最后的结点作为新结点的前继结点
057            lastNode.Prev = listNode;
058            //新结点作为最后的结点
059            listNode.Next = lastNode;
060        }
061 
062        /// <summary>
063        /// 指定元素后面插入新元素
064        /// </summary>
065        /// <param name="item">指定元素
066        /// <param name="newItem">新元素
067        public void InsertAfterByValue(T item, T newItem)
068        {
069            int location = LocateElement(item);
070            if (location < 1)
071            {
072                Console.WriteLine("Inserted Error!");
073                return;
074            }
075            //待插入结点
076            DoubleLinkedListNode<t> insertNode = new DoubleLinkedListNode<t>(newItem);
077            //插入位置为第一结点位置
078            if (location == 1)
079            {
080                //新结点的前继结点指向头结点
081                insertNode.Prev = this.nHead;
082                //新结点作为第一结点
083                this.nHead.Next = insertNode;
084            }
085            else
086            {
087                int j = 1;
088                //指向头结点
089                DoubleLinkedListNode<t> listNode = this.nHead;
090                //遍历链表,移动指针,直到指针指向指定的结点
091                while (j <= location)
092                {
093                    //移动指针,批向下一结点
094                    listNode = listNode.Next;
095                    j++;
096                }
097                //新结点的前继结点指向指定结点
098                insertNode.Prev = listNode;
099                //指定结点的后继结点作为新结点的后继结点
100                insertNode.Next = listNode.Next;
101                //指定结点的后继结点的前继结点指向新结点
102                listNode.Next.Prev = insertNode;
103                //新结点作为指定结点的后继结点
104                listNode.Next = insertNode;
105            }
106        }
107 
108        /// <summary>
109        /// 指定元素之前插入新元素
110        /// </summary>
111        /// <param name="item">指定元素
112        /// <param name="newItem">新元素
113        public void InsertBeforeByValue(T item, T newItem)
114        {
115            InsertByLocation(newItem, LocateElement(item));
116        }
117 
118        /// <summary>
119        /// 在指定位置插入元素
120        /// </summary>
121        /// <param name="item">新元素
122        /// <param name="location">链表位置
123        public void InsertByLocation(T item, int location)
124        {
125            if (location < 1 && location > this.Count())
126            {
127                Console.WriteLine("Location Is Error!");
128                return;
129            }
130            //待插入结点
131            DoubleLinkedListNode<t> insertNode = new DoubleLinkedListNode<t>(item);
132            //插入位置为第一结点位置
133            if (location == 1)
134            {
135                //新结点作为第一结点
136                this.nHead.Next = insertNode;
137                //新结点的前继结点指向头结点
138                insertNode.Prev = this.nHead;
139            }
140            else
141            {
142                //指向头结点
143                DoubleLinkedListNode<t> listNode = this.nHead;
144                int j = 1;
145                //遍历链表,移动指针,直到指向该位置的前一结点,遍历结束
146                while (j < location)
147                {
148                    listNode = listNode.Next;
149                    j++;
150                }
151                //新结点的前继结点指向指定结点
152                insertNode.Prev = listNode;
153                //指定结点的后继结点作为新结点的后继结点
154                insertNode.Next = listNode.Next;
155                //指定结点的后继结点的前继结点指向新结点
156                listNode.Next.Prev = insertNode;
157                //新结点作为指定结点的后继结点
158                listNode.Next = insertNode;
159            }
160        }

删除操作


01        /// <summary>
02        /// 删除指定位置的元素
03        /// </summary>
04        /// <param name="i">链表位置
05        public void Delete(int i)
06        {
07            if (IsEmpty())
08            {
09                Console.WriteLine("This Linear List Is Empty!");
10                return;
11            }
12            if (i < 1 && i > this.Count())
13            {
14                Console.WriteLine("Location Is Error!");
15                return;
16            }
17            int j = 1;
18            //指向头结点
19            DoubleLinkedListNode<t> listNode = this.nHead;
20            //遍历链表,移动指针,直到指针指向要删除结点的位置
21            while (j <= i)
22            {
23                listNode = listNode.Next;
24                j++;
25            }
26            //链表只有一个结点以及要删除的结点为最后一个结点的情况
27            if (this.Count() == 1 || i == this.Count())
28            {
29                //删除结点的前继结点的后继结点设为NULL
30                listNode.Prev.Next = null;
31            }
32            else
33            {
34                //删除结点的后继结点作为删除结点的前继结点的后继结点
35                listNode.Prev.Next = listNode.Next;
36                //删除结点的前继结点作为删除结点的后继结点的前继结点
37                listNode.Next.Prev = listNode.Prev;
38            }
39 
40        }