现在的位置: 首页 > 综合 > 正文

双向链表

2018年05月06日 ⁄ 综合 ⁄ 共 4972字 ⁄ 字号 评论关闭

在结点中设两个引用域,一个保存直接前驱结点的地址,叫prev,一个直接后继结点的地址,叫next,这样的链表就是双向链表(Doubly Linked List)。
 
双向链表的结点结构示意图如上,双向链表结点的定义与单链表的结点的定义很相似,因此,双向链表节点类的实现可以参考单链表的节点类。

C#实现:

1接口

引用线性表的接口IListDS<T>

2实现

(1)双向链表节点类,参考单链表的节点类
 public class DBNode<T>
{
    private T data;              //数据域
    private DBNode<T> next;        //后继
    private DBNode<T> prev;        //前驱
    public T Data
    {
        get { return data; }
        set { data = value; }
    }
    public DBNode<T> Next
    {
        get { return next; }
        set { next = value; }
    }
    public DBNode<T> Prev
    {
        get { return prev; }
        set { prev = value; }
    }
    public DBNode()
    {
        data = default(T);
        prev = null;
        next = null;
    }
    public DBNode(T val)
    {
        data = val;
        next = null;
        prev = null;
    }
}
(2) 双向链表操作类实现

注意:由于双向链表的结点有两个引用,所以,在双向链表中插入和删除结点比单链表要复杂。双向链表中结点的插入分为在结点之前插入和在结点之后插入,插入操作要对四个引用进行操作

同样,删除操作也需要多多注意,其他的操作和单链表类似,不再赘述.
 public class DBLinkList<T> : IListDS<T>
{
    private DBNode<T> header;

    public DBNode<T> Header
    {

        get { return header; }
        set { header = value; }
    }
    public DBLinkList()
    {
        header = new DBNode<T>();
        header.Next = null;
        header.Prev = null;
    }
    /// <summary>
    /// 获取长度
    /// </summary>
    /// <returns></returns>
    public int GetLength()
    {
        DBNode<T> p = header;
        int len = 0;
        while (p != null)
        {
            ++len;
            p = p.Next;
        }
        return len;
    }
    /// <summary>
    /// 清空操作
    /// </summary>
    public void Clear()
    {
        header = null;
    }
    /// <summary>
    /// 判断线性表是否为空
    /// </summary>
    /// <returns></returns>
    public bool IsEmpty()
    {
        if (header.Data == null)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    /// <summary>
    /// 查找节点
    /// </summary>
    /// <param name="i"></param>
    /// <returns></returns>
    private DBNode<T> FindNode(int i)
    {
        if (IsEmpty())
        {
            Console.Write("list is empty");
            return null;
        }
        if (i < 1)
        {
            Console.Write("Index is error");
            return null;
        }
        DBNode<T> current = new DBNode<T>();
        current = header;
        int j = 1;
        while (current.Next != null && j < i)
        {
            ++j;
            current = current.Next;
        }
        return current;
    }
    /// <summary>
    /// 插入操作,在第i个节点前面
    /// </summary>
    /// <param name="item"></param>
    /// <param name="i"></param>
    public void Insert(T item, int i)
    {
        DBNode<T> current = FindNode(i);
        DBNode<T> newNode = new DBNode<T>(item);
        if (current != null)
        {
            current.Prev.Next = newNode;
            newNode.Next = current;
            newNode.Prev = current.Prev;
            current.Prev = newNode;
        }
        else
        {
            Console.Write("the node is not exist!");
        }
    }
    /// <summary>
    /// 插入操作,在第i个节点后面插入item
    /// </summary>
    /// <param name="item"></param>
    /// <param name="i"></param>
    public void InsertBack(T item, int i)
    {
        DBNode<T> current = FindNode(i);
        DBNode<T> newNode = new DBNode<T>(item);
        if (current != null)
        {
            current.Next.Prev = newNode;
            newNode.Prev = current;
            newNode.Next = current.Next;
            current.Next = newNode;
        }
        else
        {
            Console.Write("the node is not exist!");
        }
    }
    /// <summary>
    /// 附加操作,线性表未满,将值为item的新元素添加到末尾
    /// </summary>
    /// <param name="item"></param>
    public void Append(T item)
    {
        DBNode<T> newNode = new DBNode<T>(item);
        DBNode<T> p = new DBNode<T>();
        if (header == null)
        {
            header = newNode;
            return;
        }
        p = header;

        while (p.Next != null)
        {
            p = p.Next;
        }
        p.Next = newNode;
    }

    /// <summary>
    /// 删除操作
    /// </summary>
    /// <param name="i"></param>
    /// <returns></returns>
    public T Delete(int i)
    {
        DBNode<T> current = FindNode(i);
        if (current != null)
        {
            current.Prev.Next = current.Next;
            current.Next.Prev = current.Prev;
            current.Prev = null;
            current.Next = null;
            return current.Data;
        }
        else
        {
            Console.Write("the node is not exist!");
            return default(T);
        }
    }
    /// <summary>
    /// 取表元
    /// </summary>
    /// <param name="i"></param>
    /// <returns></returns>
    public T GetElem(int i)
    {
        DBNode<T> current = FindNode(i);
        if (current != null)
        {
            return current.Data;
        }
        else
        {
            Console.Write("the node is not exist!");
            return default(T);
        }
    }

    /// <summary>
    /// 按值查找
    /// </summary>
    /// <param name="value"></param>
    /// <returns>-1:链表或参数异常;0:节点不存在;1:值代表的位置</returns>
    public int Locate(T value)
    {
        if (IsEmpty())
        {
            Console.Write("list is empty");
            return -1;
        }
        if (value == null)
        {
            Console.Write("value is empty");
            return -1;
        }
        DBNode<T> current = new DBNode<T>();
        current = header;
        int result = 0;

        while (current.Next != null)
        {
            if (current.Data.Equals(value))
            {
                result = 1;
            }
        }
        return result;
    }
}
此外,循环链表的基本操作与单链表大体相同,只是判断链表结束的条件并不是判断结点的引用域是否为空,

而是判断结点的引用域是否为头引用,其它没有较大的变化

【上篇】
【下篇】

抱歉!评论已关闭.