C#双链表

  单链表允许从一个结点直接访问它的后继结点,所以, 找直接后继结点的时间复杂度是 O(1)。但是,要找某个结点的直接前驱结点,只能从表的头引用开始遍历各结点。如果某个结点的 Next 等于该结点,那么,这个结点就是该结点的直接前驱结点。也就是说,找直接前驱结点的时间复杂度是 O(n),n是单链表的长度。当然,我们也可以在结点的引用域中保存直接前驱结点的地址而不是直接后继结点的地址。这样,找直接前驱结点的时间复杂度只有 O(1),但找直接后继结点的时间复杂度是 O(n)。如果希望找直接前驱结点和直接后继结点的时间复杂度都是 O(1),那么,需要在结点中设两个引用域,一个保存直接前驱结点的地址,叫 prev,一个直接后继结点的地址,叫 next,这样的链表就是双向链表(Doubly Linked List)。

双链表节点类的实现如下所示:

public class DbNode<T>//双向链表结点类
    {
        private T data;
        private DbNode<T> prev;
        private DbNode<T> next;

        public DbNode(DbNode<T> p, T val)
        {
            next = p;
            data = val;
        }
        public DbNode(DbNode<T> p)
        {
            next = p;
        }
        public DbNode(T val)
        {
            next = null;
            data = val;
        }
        public DbNode()
        {
            next = null;
            data = default(T);
        }

        public T Data
        {
            get { return data; }
            set { data = value; }
        }
        public DbNode<T> Prev
        {
            get { return prev; }
            set { prev = value; }
        }
        public DbNode<T> Next
        {
            get { return next; }
            set { next = value; }
        }
    }

双链表接口的实现如下所示:

public interface ILinkList<T>//双向链表接口
    {

        void AddFirst(T t);

        void AddLast(T t);

        void Clear();

        int Count { get; }

        DbNode<T> Head { get; set; }

        DbNode<T> Tail { get; set; }

        void Insert(int index, T t);

        bool IsEmpty { get; }

        void RemoveAt(int index);

        void RemoveFirst();

        void RemoveLast();

        DbNode<T> this[int index] { get; }

    }

双链表的实现如下所示:

public class LinkList<T> : ILinkList<T>
    {
        private DbNode<T> head;
        private DbNode<T> tail;
        private int size;

        public DbNode<T> Head
        {
            get { return head; }
            set { head = value; }
        }
        public DbNode<T> Tail
        {
            get { return tail; }
            set { tail = value; }
        }

        public DbNode<T> this[int index]
        {
            get
            {
                if (head == null || index < 0 || index >= Count)
                {
                    return null;
                }
                int i = 0;
                DbNode<T> current = new DbNode<T>();
                if (i < size / 2)
                {
                    current = head;
                    while (true)
                    {
                        if (i == index) { break; }
                        current = current.Next;
                        i++;
                    }
                    return current;
                }
                else
                {
                    current = tail;
                    i = size;
                    while (true)
                    {
                        if (i == index) { break; }
                        current = current.Prev;
                        i--;
                    }
                    return current.Next;
                }
            }
        }

        public bool IsEmpty
        {
            get { return head == null; }
        }

        public void AddFirst(T t)
        {
            DbNode<T> node = new DbNode<T>();
            if (head == null)
            {
                head = node;
                tail = node;
                ++size;
                return;
            }
            node.Next = head;
            head.Prev = node;
            head = node;
            ++size;
        }

        public void AddLast(T t)
        {
            DbNode<T> node = new DbNode<T>();
            if (head == null)
            {
                head = node;
                tail = node;
                ++size;
                return;
            }
            tail.Next = node;
            node.Prev = tail;
            tail = node;
            ++size;
        }

        public void Clear()
        {
            head = null;
            tail = null;
            size = 0;
        }

        public int Count
        {
            get { return size; }
        }

        public void Insert(int index, T t)
        {
            if (index < 0 || index >= Count)
            {
                return;
            }
            if (IsEmpty && index > 0)
            {
                return;
            }
            if (IsEmpty)
            {
                AddFirst(t);
                return;
            }
            DbNode<T> current = head;
            DbNode<T> node = new DbNode<T>(t);
            int i = 0;
            while (true)
            {
                if (i == index) break;
                current = current.Next;
                i++;
            }
            current.Prev.Next = node;//此处很重要
            node.Prev = current.Prev;
            node.Next = current;
            current.Prev = node;
            size++;
        }

        public void RemoveAt(int index)
        {
            if (index < 0 || index >= Count)
            {
                return;
            }
            if (IsEmpty && index > 0)
            {
                return;
            }
            if (IsEmpty)
            {
                RemoveFirst();
                return;
            }
            if (index == size - 1)
            {
                RemoveLast();
                return;
            }
            DbNode<T> current = head;
            int i = 0;
            while (true)
            {
                if (i == index) break;
                current = current.Next;
                i++;
            }
            current.Prev.Next = current.Next;
            current.Next.Prev = current.Prev;
            size--;
        }

        public void RemoveFirst()
        {
            if (IsEmpty) { return; }
            if (size == 1) { Clear(); }
            head = head.Next;
            head.Prev = null;
            size--;
        }

        public void RemoveLast()
        {
            if (IsEmpty) { return; }
            if (size == 1) { Clear(); }
            tail = tail.Prev;
            tail.Next = null;
            size--;
        }
    }
时间: 2024-08-23 23:00:32

C#双链表的相关文章

双链表的实现

双链表:可以从一个表结点出发,在线性表中随意访问它的前驱结点和后继结点,双链表有两个指针. 双链表结template<class Elem> class Link   private:       static Link<Elem>* freelist ;//Head of the freelis   public: Elem element;//value for this node Link *next;//pointer to next node in list Link *

优先双链表

题目: 设有一个双链表,每个结点中除有prior,data和 next这3个域外,还有一个访问频度域 freq,在链表被启用前其值均初始化为0.每当在在链表上进行一次查找操作Locate(L, x)时,令元素值为x的结点中的freq域的值增加1,并使此链表中的结点保持按访问频度域递减的顺序排列,以便使频繁访问的结点总是靠近表头 (1)首先创建一个双链表. (2) 设计一个符合上述要求的Locate(L, x)函数. (3) 具有输出显示访问频度功能. (4) 要求程序通过一个主菜单进行控制,在主

1216.1——双链表

双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱.所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点.一般我们都构造双向循环链表. typedef struct node{ struct node *pre;   //前驱指针 int age; struct node *next;  //后驱指针 }Node; int main(int argc, const char * argv[]) { Node * phead =

双链表优先队列ADT的实现与测试

源代码如下: #include <stdlib.h> #include <stdio.h> typedef struct pq* PQ; typedef struct PQnode* PQlink; struct Item{int data;char c;}; struct PQnode{Item key;PQlink prev,next;}; struct pq{PQlink head,tail;}; PQ PQinit(){ PQ pq = (PQ)malloc(sizeof*

双链表删除/插入节点

//双链表删除节点 dnode *del(dnode *head, int num) { dnode *p1, *p2; p1 = head; while (num != p1->data && p1->next != NULL) { p1 = p1->next; } if (num == p1->data) { if (p1 == head) { head = head->next; head->pre = NULL; free(p1); } else

redis源码分析(3)-- 基本数据结构双链表list

一.双链表结构 redis中实现的双链表结构体如下: 1 typedef struct list { 2 listNode *head; # 链表头 3 listNode *tail; # 链表尾 4 void *(*dup)(void *ptr); # 复制链表函数 5 void (*free)(void *ptr); # 释放节点函数 6 int (*match)(void *ptr, void *key); # 匹配函数 7 unsigned long len; # 链表节点个数 8 }

线性表—双链表

1.基础知识 a.双链表结点的结构:其由前序元素地址,数据域,后继元素地址组成. b.双链表结点的连接方法:先声明该结点,可以在内部也可以利用其特性来表明前序结点和后继结点是什么,之后同时还需要说明"其前序结点的后继地址为该结点"和"其后继结点的前序地址为该结点.(本质:双向) 2.循环双链表的实现 线性表接口LList package com.clarck.datastructure.dlinked; /*** 线性表接口LList,描述线性表抽象数据类型,泛型参数T表示数

约瑟夫问题 双链表实现

<span style="color:#cc33cc;"> /********************************* author : Grant Yuan algorithm; 双链表. time :2014/10/3 20:38 *********************************/ #include<iostream> #include <cstdio> #include<cstring> #include

双链表&amp;链表合并&amp;多项式相加算法

//单链表的合并 //链表合并 //两个链表必须是有序的 #define Maxsize 5 typedef  int elemtype; typedef struct linklist { elemtype data; struct linklist *next; }Linklist; //建立链表1 Linklist *CreateList1 () { int i,data ; Linklist *head, *p, *q; head=p=(Linklist  *)malloc(sizeof

c++双链表【构造函数、运算符重载、析构函数、增删查改及逆置等】

c++中的双向链表写法,主要实现(增删查改,链表逆置,构造函数,运算符重载,等) 建立头文件SList.h #pragma once typedef int DataType; class ListNode { friend class List;//友元函数 public: ListNode(const DataType x) :_data(x) , _prev(NULL) , _next(NULL) {} private: DataType _data; ListNode* _prev; L