双向链表基本操作实现--建议做题时画图 切不可死记

// 殷人昆双向链表c第2版51页.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//2024-10-8---感受编程的技巧和乐趣

#include <iostream>

typedef int datatype;
using namespace std;
typedef struct node {
    datatype data;
    int freq;
    struct node* rLink, * lLink;
}dblnode,*dblist;
void createR(dblist& first, datatype a[], int m)
{
    first = (dblist)malloc(sizeof(dblnode));//create head 节点
    first->lLink = first->rLink = first;//initalize
    dblnode* s, * q, * rear = first;
    for (int i = 0; i < m; i++)
    {
        s = (dblist)malloc(sizeof(dblnode));
        s->data = a[i];
        //相当于双向循环链表的插入
        q = rear->rLink; s->lLink = rear; q->lLink = s;//前驱方向链接
        s->rLink = q; rear->rLink = s; rear = s;//后继方向链接
        //借助指针q记录rear的后继地址,避免断链
    }
}
void printlist(dblist first)
{
    dblist p;
    p = first->rLink;
    while (p != first)
    {
        cout << p->data << " ";
        p = p->rLink;
    }
    cout << endl;
}
dblist search(dblist first,datatype x)
{
    dblist p = first->rLink;
    while (p != first && p->data != x)//动动脑子,再写
    {
        p = p->rLink;
    }
    return (p != first) ? p : NULL;//NULL是p==first的情况没有找到
}
dblist locate(dblist first, int i)
{
    if (i < 0)return NULL;//i=0是头节点,i<0插入位置不合理
    if (i == 0)return first;
    dblist p = first->rLink;
    for (int j = 1; j < i; j++)
    {
        if (p == first)
        {
            break;//i太大,链太短
        }else {
            p = p->rLink;
        }
    }
    return (p != first) ? p : NULL;//NULL是first==p位置小于0,或i>链表长度
}
int insert(dblist& first, int i, datatype x, int d)
{
    dblist p = locate(first,i-1);
    if (p == NULL)return 0;//i-1<0或i-1>长度,插入位置不合理
    dblist s = new dblnode;
    s->data = x;
    if (d == 0)//前驱方向加入
    {
        s->rLink = p; s->lLink = p->lLink;//我采用的是保险的做法,先解决插入节点,这样不会断链
        p->lLink->rLink = s; p->lLink = s;//为了不断链,最后修改p->lLink
    }
    else//后继
    {
        s->rLink = p->rLink; s->lLink = p;
        p->rLink->lLink = s; p->rLink = s;//为了不断链,最后修改p->rLink
    }
    return 1;
}
int insert_yinrenkun(dblist& first, int i, datatype x, int d)
{
    dblist p = locate(first, i - 1);
    if (p == NULL)return 0;//i-1<0或i-1>长度,插入位置不合理
    dblist s = new dblnode;
    s->data = x;
    if (d == 0)//前驱方向加入
    {
         s->lLink = p->lLink; p->lLink = s;//前驱链
         s->lLink->rLink = s; s->rLink = p;//后继链
    }
    else//后继
    {
        s->rLink = p->rLink; p->rLink = s;//后继链
        
        s->rLink->lLink = s; s->lLink = p;//前驱链
    }
    return 1;
}
int remove_wanghongmei(dblist& first, int i, datatype& x)
{
    dblist p = locate(first,i);
    if (p == NULL)return 0;//空表或位置不对,删除位置1<=i=<长度
    p->lLink->rLink = p->rLink;
    p->rLink->lLink = p->lLink;
    x = p->data;
    free(p);
    p = NULL;
    return 1;
}
int remove(dblist& first, int i, datatype& x)
{
    dblist p = locate(first,i);
    if (p == NULL)return 0;
    p->rLink->lLink = p->lLink;
    p->lLink->rLink = p->rLink;
    free(p);
    return 1;
}
int main()
{
    int a[6] = {2,3,5,7,9,1};
    dblist first;
    createR(first, a, 6);
    printlist(first);
    dblist p = search(first, 9);
    cout << p->data<<endl;
    p = locate(first,3);
    cout << p->data << endl;
    p = locate(first, 7);
    if (p == NULL) {
        cout << "p==null" << endl;
    }
    insert_yinrenkun(first, 4, 6, 1);
    printlist(first);
    datatype x;
    remove_wanghongmei(first, 4, x);
    printlist(first);
    std::cout << "Hello World!\n";
}


解决问题:王红梅老师的删除节点----修改指针两条语句可以颠倒吗?可以,殷人昆就是这样做的

另外解决问题之前,自己先想想!!!!

仔细体会殷人昆老师的代码和习题,里面有很多编程的小技巧!!!

关于插入操作-----上面的代码不是唯一的,但也不可以任意排序 思考:第一步和第二步是不是必须在第四步最后??上面的代码不是唯一的,但也不可以任意排序 ;;;否则*p的后继节点的指针就会丢掉,插入失败。

建议做题时画图 切不可死记

例如:尾插法---我根据循环链表进行了修改

void createRear(dblist& first, datatype a[], int m)//我自己写的---根据单链表的尾插法
{
    first = new dblnode;
    first->lLink = first->rLink=first;
    dblist s, rear = first;
    for (int i = 0; i < m; i++)
    {
        s = new dblnode;
        s->data = a[i];
        s->lLink = rear;
        s->rLink = rear->rLink;
        rear->rLink = s;//上面两句和这一句修改指针将s节点插入到链表尾部
        rear = s;//rear后移,指向目前最后一个节点
    }
}

在写代码时,我忘记写rear->next=s;其实书上写的都有,

可见学习需要循序渐进,不着急按照殷人昆老师的讲解,

一页页的看!!

s->next=rear->next等价于s->next=first;;因为是循环链表,无论循环链表是双向的还是单向的!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值