简单实现一个双向循环链表

胆大心细,加油。

简单实现一个双向循环链表

最近看公司代码的时候,发现有些业务是自己实现和封装的数据结构,以双向循环链表居多(大佬们写的代码真好),所以就复习一下双向循环链表的知识并自己实现了一个双向循环链表。

双向循环链表特征

双向链表是每个结点除后继指针外还有一个前驱指针。和单链表类同,双向链表也有带头结点结构和不带头结点结构两种,带头结点的双向链表更为常用;另外,双向链表也可以有循环和非循环两种结构,循环结构的双向链表更为常用。

双向循环链表数据结构

在双向链表中,每个结点包括三个域,分别是element域、next域和prior域,其中element域为数据元素域,next域为指向后继结点的对象引用,prior域为指向前驱结点的对象引用。双向链表结点的图示结构如下:
数据结构

双向循环列表关系图示和插入删除操作

在双向链表中,有如下关系:设对象引用p表示双向链表中的第i个结点,则p.next表示第i+1个结点,p.next.prior仍表示第i个结点,即p.next.prior == p;同样地,p.prior表示第i-1个结点,p.prior.next仍表示第i个结点,即p.prior.next == p。下图是双向链表上述关系的图示。
双向循环链表
循环双向链表的插入过程如下图所示。图中的指针p表示要插入结点的位置,s表示要插入的结点,①、②、③、④表示实现插入过程的步骤。
插入过程
循环双向链表的删除过程如下图所示。图中的指针p表示要插入结点的位置,①、②表示实现删除过程的步骤。
删除

代码实现

1. 链表常见操作接口
  public interface List {
    int size();
    void insert(int index,Object value) throws Exception;
    void delete(int index) throws Exception;
    Object get(int index) throws Exception;
    boolean isEmpty();
}
2. 链表节点
/**
 * @author wencai.xu
 */
public class DoubleListNode {
    /**
     * 节点值
     */
     Object element;
    /**
     * 前驱
     */
     DoubleListNode prior;
    /**
     * 后继
     */
     DoubleListNode next;
    /**
     * 头节点
     * @param nextval
     */
    public DoubleListNode(DoubleListNode nextval) {
        this.next = nextval;
    }
    /**
     * 非头节点
     * @param element
     * @param next
     */
    public DoubleListNode(Object element, DoubleListNode next) {
        this.element = element;
        this.next = next;
    }
    public Object getElement() {
        return element;
    }
    public void setElement(Object element) {
        this.element = element;
    }
    public DoubleListNode getPrior() {
        return prior;
    }
    public void setPrior(DoubleListNode prior) {
        this.prior = prior;
    }
    public DoubleListNode getNext() {
        return next;
    }
    public void setNext(DoubleListNode next) {
        this.next = next;
    }
    @Override
    public String toString(){
        return this.element.toString();
    }
}
3. 数据结构操作实现
public class DoubleLinkedList implements List{
    /**
     * 链表长度
     */
    private int size;
    /**
     * 头指针
     */
    private DoubleListNode head;

    /**
     * 当前指针
     */
    private DoubleListNode current;

    public DoubleLinkedList() {
        this.head = current = new DoubleListNode(null);
        // 初始长度为0
        this.size = 0;
        // 头节点的前趋和后继都指向头节点
        this.head.next = head;
        this.head.prior = head;
    }
    @Override
    public int size() {
        return this.size;
    }

    /**
     * 定位函数
     */
    private void index(int index) throws Exception {
        if(index < -1 || index > size - 1){
            throw new Exception("参数失败");
        }
        // 头节点
        if(index == -1){
            return;
        }
        int j = 0;
        current = head.next;
        while(current != head && j < index){
            current = current.next;
            j++;
        }
    }
    @Override
    public void insert(int index, Object value) throws Exception {
        if(index < 0 || index > size){
            throw new Exception("参数错误");
        }
        index(index - 1);
        current.setNext(new DoubleListNode(value,current.next));
        current.next.setPrior(current);
        current.next.next.setPrior(current.next);
        size ++;
    }
    @Override
    public void delete(int index) throws Exception {
        if(isEmpty()){
            throw new Exception("链表为空,无法删除");
        }
        if(index < 0 || index > size){
            throw new Exception("参数错误");
        }
        index(index - 1);
        current.setNext(current.next.next);
        current.next.setPrior(current);
        size --;
    }

    @Override
    public Object get(int index) throws Exception {
        if(index < 0 || index > size - 1){
            throw new Exception("参数失败");
        }
        index(index);
        return current.element;
    }

    @Override
    public boolean isEmpty() {
        return this.size == 0;
    }
}

4. 测试

public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        DoubleLinkedList list = new DoubleLinkedList();
        for(int i=0;i<10;i++)
        {
            int temp = ((int)(Math.random()*100))%100;
            list.insert(i, temp);
            System.out.print(temp+" ");
        }
        list.delete(4);
        System.out.println("\n------删除第五个元素之后-------");
        for(int i=0;i<list.size;i++)
        {
            System.out.print(list.get(i)+" ");
        }
    }

关注我

关注我

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用C语言实现双向循环链表的代码: ```c #include <stdio.h> #include <stdlib.h> // 定义链表节点结构体 typedef struct node { int data; struct node *prev; struct node *next; } Node; // 初始化链表 Node *initList() { Node *head = (Node *)malloc(sizeof(Node)); head->data = 0; head->prev = head; head->next = head; return head; } // 插入节点 void insertNode(Node *head, int data) { Node *p = (Node *)malloc(sizeof(Node)); p->data = data; p->prev = head; p->next = head->next; head->next->prev = p; head->next = p; } // 删除节点 void deleteNode(Node *head, int data) { Node *p = head->next; while (p != head) { if (p->data == data) { p->prev->next = p->next; p->next->prev = p->prev; free(p); return; } p = p->next; } } // 打印链表 void printList(Node *head) { Node *p = head->next; while (p != head) { printf("%d ", p->data); p = p->next; } printf("\n"); } int main() { Node *head = initList(); insertNode(head, 1); insertNode(head, 2); insertNode(head, 3); printList(head); deleteNode(head, 2); printList(head); return 0; } ``` 代码解释: 1. 定义链表节点结构体,包含数据、前驱节点和后继节点。 2. 初始化链表,创建一个头节点,数据为0,前驱节点和后继节点均指向自身。 3. 插入节点,创建一个新节点,将其插入到头节点之后。 4. 删除节点,从头节点之后开始遍历链表,找到要删除的节点,将其从链表中删除。 5. 打印链表,从头节点之后开始遍历链表,打印每个节点的数据。 6. 在主函数中使用链表的各种操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值