【数据结构】线性表-双向链表(图解、c++、java)

文章目录

  • 双向链表的存储方式(图解)
  • 双向链表的基本操作
    • 1.初始化
    • 2.创建
    • 3.插入
    • 4.删除
    • 5.打印
    • 6.释放内存
  • 完整代码
  • 总结

GitHub同步更新(已分类):Data_Structure_And_Algorithm-Review

公众号:URLeisure 的复习仓库
公众号二维码见文末

以下是本篇文章正文内容,下面案例可供参考。


双向链表的存储方式(图解)

  • 学会了单链表,双向链表就很好理解。

  • 相对于单链表,双向链表只是又多了一个指针域,来存储上一个节点的地址,达到可以向前操作的效果。

双向链表

双向链表的基本操作

因为双向链表与单链表的类似,查找代码相同,这里就不再写了。

  • 首先定义一个结构体(内部类),包含数据域与两个指针域。

c++代码如下(示例):

typedef struct DulNode {
    int data;
    DulNode *prior, *next;
} *DulList;

java代码如下(示例):

public static class DulNode {
    int data;
    DulNode prior, next;
}

1.初始化

  • 双向链表的初始化是指构建一个空表。先创建一个头节点,不存储数据,然后令其前后两个指针域为空(判断终止时会用到)。

c++代码如下(示例):

bool Init(DulList &L) {
    L = new DulNode;
    if (!L) {
        return false;
    }
    L->prior = L->next = NULL;
    return true;
}

java代码如下(示例):

public static DulNode init() {
    DulNode dulNode = new DulNode();
    dulNode.next = dulNode.prior = null;
    return dulNode;
}

2.创建

  • 创建双向链表也可以用头插法和尾插法。

  • 我们以头插法为例,尾插法与头插法改法相似,不再赘述。

【数据结构】线性表-双向链表(图解、c++、java)_第1张图片

c++代码如下(示例):

void Create_H(DulList &L, int n) {//n元素个数
    DulList s;
    while (n--) {
        s = new DulNode;
        cin >> s->data;
        if (L->next) {//判断头节点后有没有元素
            L->next->prior = s;//如果没有元素,就没有L->next->prior,会出bug
        }
        s->next = L->next;
        s->prior = L;
        L->next = s;
    }
}

java代码如下(示例):

public static void create_H(DulNode L, int n) {
	DulNode s;
	Scanner sc = new Scanner(System.in);
	while (n-- > 0) {
        s = new DulNode();
        s.data = sc.nextInt();
        if (L.next != null) {
            L.next.prior = s;
        }
        s.next = L.next;
        s.prior = L;
        L.next = s;
    }
}

3.插入

【数据结构】线性表-双向链表(图解、c++、java)_第2张图片

  • ②、③ 位置不能颠倒。

c++代码如下(示例):

bool Insert(DulList &L, int i, int e) {
    DulList s, p = L;
    int j = 0;
    while (p && j < i - 1) {
        p = p->next;
        j++;
    }
    if (!p || j > i - 1) {
        return false;
    }
    s = new DulNode;
    s->data = e;

    if (p->next) {//如果p->next为空,则不存在p->next->prior,会出bug
        p->next->prior = s;
    }
    s->next = p->next;
    s->prior = p;
    p->next = s;
    return true;
}

java代码如下(示例):

public static boolean insert(DulNode L, int i, int e) {
    DulNode s, p = L;
    int j = 0;
    while (p != null && j < i - 1) {
        p = p.next;
        j++;
    }
    if (p == null || j > i - 1) {
        return false;
    }
    s = new DulNode();
    s.data = e;
    if (p.next != null) {
        p.next.prior = s;
    }
    s.next = p.next;
    s.prior = p;
    p.next = s;
    return true;
}

4.删除

  • 删除一个节点,就是把这个节点跳过去。(可以不找 i-1 个,找第i个也行)
    【数据结构】线性表-双向链表(图解、c++、java)_第3张图片

c++代码如下(示例)找第i-1个:

bool Delete(DulList &L, int i, int &e) {
    DulList q, p = L;
    int j = 0;
    while (p && j < i - 1) {
        p = p->next;
        j++;
    }
    if (!p || j > i) {
        return false;
    }
    q = p->next;
    if (q->next) {//如果p->next为空,则不存在p->next->prior,会出bug
        q->next->prior = p;
    }
    p->next = q->next;//跨过q
    e = q->data;
    delete q;
    return true;
}

java代码如下(示例)找第i个:

public static int delete(DulNode L, int i) {
	DulNode p = L.next;
    int j = 1;
    while (p != null && j < i) {
        p = p.next;
        j++;
    }
    if (p == null || j > i) {
        return -1;
    }
	if (p.next != null) {
        p.next.prior = p.prior;
    }
    p.prior.next = p.next;
    return p.data;
}

5.打印

  • 打印非常简单,直接上代码。

c++代码如下(示例):

void Print(DulList L) {
    DulList p;
    p = L->next;
    while (p) {
        cout << p->data << " ";
        p = p->next;
    }
    cout << endl;
}

java代码如下(示例):

public static void print(DulNode L) {
    DulNode p = L.next;
    while (p.next != null) {
        p = p.next;
    }
    while (p != null) {
        System.out.print(p.data + " ");
        p = p.prior;
    }
    System.out.println();
}

6.释放内存

  • c++ 需要手动释放内存,而 java 不需要。

c++代码如下(示例):

void Destroy(DulList &L) {
    DulList tmp;
    for (DulList cur = L->next; cur != NULL;) {
        tmp = cur;
        cur = cur->next;
        delete tmp;
    }
    delete L;
}

完整代码

c++代码如下(示例):

#include

using namespace std;

typedef struct DulNode {
    int data;
    DulNode *prior, *next;
} *DulList;

bool Init(DulList &L) {
    L = new DulNode;
    if (!L) {
        return false;
    }
    L->prior = L->next = NULL;
    return true;
}

void Create_H(DulList &L, int n) {//n元素个数
    DulList s;
    while (n--) {
        s = new DulNode;
        cin >> s->data;
        if (L->next) {//判断头节点后有没有元素
            L->next->prior = s;//如果没有元素,就没有L->next->prior,会出bug
        }
        s->next = L->next;
        s->prior = L;
        L->next = s;
    }
}

bool Insert(DulList &L, int i, int e) {
    DulList s, p = L;
    int j = 0;
    while (p && j < i - 1) {
        p = p->next;
        j++;
    }
    if (!p || j > i - 1) {
        return false;
    }
    s = new DulNode;
    s->data = e;

    if (p->next) {//如果p->next为空,则不存在p->next->prior,会出bug
        p->next->prior = s;
    }
    s->next = p->next;
    s->prior = p;
    p->next = s;
    return true;
}

bool Delete(DulList &L, int i, int &e) {
    DulList q, p = L;
    int j = 0;
    while (p && j < i - 1) {
        p = p->next;
        j++;
    }
    if (!p || j > i) {
        return false;
    }
    q = p->next;
    if (q->next) {//如果p->next为空,则不存在p->next->prior,会出bug
        q->next->prior = p;
    }
    p->next = q->next;//跨过q
    e = q->data;
    delete q;
    return true;
}

void Print(DulList L) {
    DulList p;
    p = L->next;
    while (p) {
        cout << p->data << " ";
        p = p->next;
    }
    cout << endl;
}

void Destroy(DulList &L) {
    DulList tmp;
    for (DulList cur = L->next; cur != NULL;) {
        tmp = cur;
        cur = cur->next;
        delete tmp;
    }
    delete L;
}

int main() {
    DulList L;
    int choose = -1;
    int i, e, x, n;
    
    Init(L);//初始化
    cout << "输入元素个数:" << endl;
    cin >> n;
    
    cout << "依次输入要插入的元素" << endl;
    Create_H(L, n);
    cout << "双向链表表创建成功!" << endl;

    cout << "1 .插入\n";
    cout << "2 .删除\n";
    cout << "3 .输出\n";
    cout << "0 .退出\n";
    while (choose != 0) {
        cout << "请选择!" << endl;
        cin >> choose;
        switch (choose) {
            case 1:
                cout << "请输入要插入的位置和要插入的元素" << endl;
                cin >> i >> e;
                if (Insert(L, i, e)) {
                    cout << "插入成功!" << endl;
                } else {
                    cout << "插入失败!" << endl;
                }
                break;
            case 2:
                cout << "请输入要删除的位置i" << endl;
                cin >> i;
                if (Delete(L, i, e)) {
                    cout << "成功删除" << e << endl;
                } else {
                    cout << "删除失败!" << endl;
                }
                break;
            case 3:
                Print(L);
                break;
            case 0:
                cout << "成功退出" << endl;
                break;
        }
    }
    Destroy(L);
    return 0;
}

java代码如下(示例):

public class A {

    public static class DulNode {
        int data;
        DulNode prior, next;
    }

    public static DulNode init() {
        DulNode dulNode = new DulNode();
        dulNode.next = dulNode.prior = null;
        return dulNode;
    }

    public static void create_H(DulNode L, int n) {
        DulNode s;
        Scanner sc = new Scanner(System.in);
        while (n-- > 0) {
            s = new DulNode();
            s.data = sc.nextInt();
            if (L.next != null) {
                L.next.prior = s;
            }
            s.next = L.next;
            s.prior = L;
            L.next = s;
        }
    }

    public static boolean insert(DulNode L, int i, int e) {
        DulNode s, p = L;
        int j = 0;
        while (p != null && j < i - 1) {
            p = p.next;
            j++;
        }
        if (p == null || j > i - 1) {
            return false;
        }
        s = new DulNode();
        s.data = e;
        if (p.next != null) {
            p.next.prior = s;
        }
        s.next = p.next;
        s.prior = p;
        p.next = s;
        return true;
    }

    public static int delete(DulNode L, int i) {
        DulNode p = L.next;
        int j = 1;
        while (p != null && j < i) {
            p = p.next;
            j++;
        }
        if (p == null || j > i) {
            return -1;
        }
        if (p.next != null) {
            p.next.prior = p.prior;
        }
        p.prior.next = p.next;
        return p.data;
    }

    public static void print(DulNode L) {
        DulNode p = L.next;
        while (p.next != null) {

            p = p.next;
        }
        while (p != null) {
            System.out.print(p.data + " ");
            p = p.prior;
        }
        System.out.println();
    }

    public static void main(String[] args) {
        DulNode L;
        int n, e, i;
        Scanner sc = new Scanner(System.in);

        L = init();//初始化

        System.out.println("输入元素个数:");
        n = sc.nextInt();
        
        System.out.println("依次输入要插入的元素");
        create_H(L, n);
        System.out.println("创建成功!");
        
        System.out.print("1.插入\n2.删除\n3.打印\n0.退出\n");
        int choose = -1;
        while (choose != 0) {
            choose = sc.nextInt();
            switch (choose) {
                case 1:
                    System.out.println("请输入要插入的位置和元素");
                    i = sc.nextInt();
                    e = sc.nextInt();
                    if (insert(L, i, e)) {
                        System.out.println("插入成功!");
                    } else
                        System.out.println("插入失败!");
                    break;
                case 2:
                    System.out.println("请输入要删除的位置");
                    i = sc.nextInt();
                    System.out.println("已删除" + delete(L, i));
                    break;
                case 3:
                    print(L);
                    break;
                case 0:
                    break;
            }
        }
    }
}

总结

  • 对于学会了单链表的人来说,双向链表看一看就差不多会了。

  • 单链表和双链表的区别也就是,一个不可以向前操作,另一个可以向前操作。

  • 同时记着在插入和删除时修改 prior 指针节点。


关注公众号,感受不同的阅读体验

请添加图片描述

下期预告: 循环链表

你可能感兴趣的:(链表,数据结构,java,c++,图解法)