C#数据结构——双向链表的实现
双向链表的说明:
在单向链表的存储结构中,只有一个指示直接后继的指针域,由此从某个节点出发只能顺指针往后查询其他节点。如果要查询节点的直接前驱,则需要从表头指针出发。为了克服单链表这种单向性的缺点,可以使用双向链表。在双向链表的节点中有两个指针域,其一指向直接前驱,另一个指向直接后继。
关键技术
双向链表的算法描述和单向链表基本相同,具体基础知识可以参照实例“链表的实现”,但是双向链表在删除和插入时与单向链表有很大的不同。双向链表在删除节点时,不但要修改节点的直接后继指针,还要同时修改节点的直接前驱指针。在插入时更是要修改插入节点的前驱和后继的两个方向上的指针。
设计过程
(1)打开Visual Studio 开发环境,新建一个类库项目,命名为BothChainTable。
(2)将“Class1.cs”文件重命名为“DoubleLink.cs”。
(3)程序主要代码如下:
构造函数代码如下:
public Objects(int num, string Name, int count)//构造函数
{
//获取参数值
number = num;
name = Name;
counter = count;
}
public int Number//定义变量
{
get//访问器
{
return number;//获取值
}
set //访问器
{
number = value; //设置值
}
}
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
public int Counter
{
get
{
return counter;
}
set
{
counter = value;
}
}
定义链表中的节点的实现代码如下:
public class ListNode//类
{
public ListNode(Objects bugs) //构造函数
{
goods = bugs;
}
public ListNode Previous; //前一个
public ListNode Next; //后一个
public ListNode next
{
get
{
return Next;
}
set
{
Next = value;
}
}
public Objects goods;//值
public Objects Goods
{
get
{
return goods;
}
set
{
goods = value;
}
}
}
定义链表类的实现代码如下:
public Clists() //构造函数
{
ListCountValue = 0; //初始化
Head = null;
Tail = null;
}
private string clistname = ""; //表名
public string ClistName
{
get
{
return clistname;
}
set
{
clistname = value;
}
}
private ListNode Head; //头指针
private ListNode Tail; //尾指针
private ListNode Current; //当前指针
public ListNode current
{
get
{
return Current;
}
set
{
Current = value;
}
}
private int ListCountValue; //链表数据的个数
在链表尾部添加数据的实现代码如下:
public void Append(Objects DataValue)
{
ListNode NewNode = new ListNode(DataValue);
if (IsNull()) //如果头指针为空
{
Head = NewNode;
Tail = NewNode;
}
else
{
Tail.Next = NewNode;
NewNode.Previous = Tail;
Tail = NewNode;
}
Current = NewNode;
ListCountValue += 1; //链表数据个数加一
}
删除当前数据的实现代码如下:
public void Delete()
{
if (!IsNull()) //若为空链表
{
if (IsBof()) //若删除头
{
Head = Current.Next;
Current = Head;
ListCountValue -= 1;
return;
}
if (IsEof()) //若删除尾
{
Tail = Current.Previous;
Tail.next = null;
Current = Tail;
ListCountValue -= 1;
return;
}
Current.Previous.Next = Current.Next;
Current = Current.Previous;
ListCountValue -= 1;
return;
}
}
public void MoveNext()
{
if (!IsEof()) Current = Current.Next; //向后移动一个数据
}
public void MovePrevious()
{
if (!IsBof()) Current = Current.Previous; //向前移动一个数据
}
public void MoveFrist()
{
Current = Head; //移动到第一个数据
}
public void MoveLast()
{
Current = Tail; //移动到最后一个数据
}
public bool IsNull()
{
if (ListCountValue == 0) //判断是否为空链表
return true;
else
return false;
}
public bool IsEof()
{
if (Current == Tail) //判断是否到达尾部
return true;
else
return false;
}
public bool IsBof()
{
if (Current == Head) //判断是否到达头部
return true;
else
return false;
}
public Objects GetCurrentValue() //获取值
{
return Current.goods;
}
public int ListCount
{
get
{
return ListCountValue; //取得链表的数据个数
}
}
清空链表的实现代码如下:
public void Clear()
{
MoveFrist();
while (!IsNull())
{
Delete(); //若不为空链表,从尾部删除
}
}
public void Insert(Objects DataValue) //在当前位置前插入数据
{
ListNode NewNode = new ListNode(DataValue);
if (IsNull())
{
Append(DataValue); //为空表,则添加
return;
}
if (IsBof())
{
//为头部插入
NewNode.Next = Head;
Head.Previous = NewNode;
Head = NewNode;
Current = Head;
ListCountValue += 1;
return;
}
NewNode.Next = Current; //中间插入
NewNode.Previous = Current.Previous;
Current.Previous.Next = NewNode;
Current.Previous = NewNode;
Current = NewNode;
ListCountValue += 1;
}
升序插入的实现代码如下:
public void InsertAscending(Objects InsertValue)
{
//参数:InsertValue 插入的数据
if (IsNull()) //为空链表
{
Append(InsertValue); ///添加
return;
}
MoveFrist(); //移动到头
if ((InsertValue.Number < GetCurrentValue().Number))
{
Insert(InsertValue); //满足条件,则插入,退出
return;
}
while (true)
{
if (InsertValue.Number < GetCurrentValue().Number)
{
Insert(InsertValue); //满足条件,则插入,退出
break;
}
if (IsEof())
{
Append(InsertValue); //尾部添加
break;
}
MoveNext(); //移动到下一个指针
}
}
降序插入的实现代码如下:
public void InsertUnAscending(Objects InsertValue)
{
//参数:InsertValue 插入的数据
if (IsNull()) //为空链表
{
Append(InsertValue); //添加
return;
}
MoveFrist(); //移动到头
if (InsertValue.Number > GetCurrentValue().Number)
{
Insert(InsertValue); //满足条件,则插入,退出
return;
}
while (true)
{
if (InsertValue.Number > GetCurrentValue().Number)
{
Insert(InsertValue); //满足条件,则插入,退出
break;
}
if (IsEof())
{
Append(InsertValue); //尾部添加
break;
}
MoveNext(); //移动到下一个指针
}
}
技巧与心得
一个算法应该具有以下特点:
- 有穷性:一个算法必须在执行有穷多个计算机步骤后终止;
- 确定性:一个算法给出的每个计算步骤,必须是有精确定义、无二义性;
- 有效性:算法中的每一个步骤必须有效地执行,并能得到确定结果;
- 输入:一个算法中可以没有输入,也可以有一个或多个输入信息。这些输入信息是算法所须的初始数据;
- 输出:一个算法应有一个或多个输出,一个算法得到的结果(中间结果或最后结果)就是算法的输出,没有输出的算法是没有意义的。