双向链表笔记

双向链表增删,准备未来复习自己用

#include <bits/stdc++.h>

using namespace std;

typedef struct node
{
    int data;
    struct node *next,*pre;
}NODE;
///测试双向链表
void showLink(NODE *p)
{
    while(p)
    {
        printf("%d ",p->data);
        p=p->next;
    }
    puts("");
}
///双向链表插入
void addNode(NODE *head,NODE *tail)
{
    int x;
    puts("请输入插入的数字X,将在X后添加X");
    scanf("%d",&x);
    NODE *p=head,*q;
    ///在尾部添加
    if(tail->data==x)
    {
        q=(NODE *)malloc(sizeof(NODE));
        q->data=x;
        tail->next=q;
        q->pre=tail;
        tail=q;
        tail->next=NULL;
        return ;
    }
    ///在中间添加
    while(p)
    {
        if(p->data==x)
        {
            q=(NODE *)malloc(sizeof(NODE));
            q->data=x;
            q->pre=p;
            q->next=p->next;
            q->next->pre=q;
            p->next=q;
            ///break;///加上break只找一个x,不加找所有x
        }
        p=p->next->next;///添加x后,p要跳过添加的x否则在加的x后加x而死循环。正常只需一个next
    }
}
///删除节点
void delNode(NODE **head,NODE **tail)
{
    int x;
    NODE *p=(*head),*q=p->next;
    if(*head==NULL)
    {
        puts("链表空");
        return ;
    }
    puts("请输入删除结点的数值:");
    scanf("%d",&x);
    ///删除头结点
    if((*head)->data==x)
    {
        q=*head;
        *head=(*head)->next;
        (*head)->pre=NULL;
        free(q);
        return ;
    }
    ///删除尾结点
    if((*tail)->data==x)
    {
        q=*tail;
        *tail=(*tail)->pre;
        (*tail)->next=NULL;
        free(q);
        return ;
    }
    ///删除中间结点
    while(q)
    {
        if(q->data==x)
        {
            p->next=q->next;
            q->next->pre=p;
            q=p->next;
        }
        else
        {
            q=q->next;
            p=p->next;
        }
    }
}
int main()
{
    int a;
    NODE *head,*tail,*p;
    head=tail=NULL;
    while(~scanf("%d",&a))
    {
        p=(NODE *)malloc(sizeof(NODE));
        p->data=a;
        p->next=NULL;
        p->pre=NULL;
        if(head==NULL)
        {
            head=tail=p;
        }
        else
        {
            tail->next=p;
            p->pre=tail;
            tail=p;
        }
    }
    //showLink(tail);
    //addNode(head,tail);
    delNode(&head,&tail);//删除头结点,尾结点需要改变头尾指针所以用双重指针
    showLink(head);
    return 0;
}
时间: 2024-10-21 07:02:45

双向链表笔记的相关文章

C++ Primer 学习笔记_13_标准模板库_list双向链表容器

C++ Primer 学习笔记_13_标准模板库_list双向链表容器 list容器实现了双向链表的数据结构,数据元素是通过链表指针串连成逻辑意义上的线性表,这样,对链表的任一位置的元素进行插入.删除和查找都是超快速的.下图是双向循环链表的结构示意图. list的每个节点有三个域:前驱元素指针域.数据域和后继元素指针域.前驱元素指针域保存了前驱元素的首地址:数据域则是本节点的数据:后继元素指针域则保存了后继元素的首地址.list的头结点的前驱元素指针域保存的是链表中尾元素的首地址,而list的尾

20、蛤蟆的数据结构笔记之十九双向链表

20.蛤蟆的数据结构笔记之十九双向链表 本篇名言:"人的生命,似洪水奔流,不遇着岛屿和暗礁,难以激起美丽的浪花." 之前实现的都是单向列表,那么我们来看下双向链表. 欢迎转载,转载请标明出处: 1.  双向链表 双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱.所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点.一般我们都构造双向循环链表. 2.  定义结构体 typedef struct DoubleLinked

数据结构笔记4双向链表

#include<stdio.h>#include<malloc.h>#include<conio.h>#define OK 1#define ERROR -1#define OVERFLOW -2#define ENDFlAG 0//双向链表节点 struct DNode{ int data; struct DNode *prior,*next;}DNode,*DLinkList;//初始化以及建立,采用尾插法,返回1 int InitLinkList_Asighme

[读书笔记]-大话数据结构-3-线性表(三)-静态链表、循环链表和双向链表

静态链表 对于没有指针的编程语言,可以用数组替代指针,来描述链表.让数组的每个元素由data和cur两部分组成,其中cur相当于链表的next指针,这种用数组描述的链表叫做静态链表,这种描述方法叫做游标实现法.我们对数组的第一个和最后一个元素做特殊处理,不存数据.让数组的第一个元素cur存放第一个备用元素(未被占用的元素)下标,而数组的最后一个元素cur存放第一个有值的元素下标,相当于头结点作用.空的静态链表如下图 当存放入一些数据时("甲""乙""丁&q

SPL笔记之双向链表

SplDoublyLinkedList rewind:使链表的当前指针指向链表的底部(bottom) push:向链表的顶部(尾部)插入一个节点 pop:获取链表中的顶部(尾部)节点,并且从链表中删除这个节点;操作不改变当前指针的位置 current:指向链表当前节点的指针,必须在调用之前先调用rewind.当指向的节点被删除之后,会指向一个空节点. next:让链表当前节点的指针指向下一个节点,current的返回值随之改变 unshift:向链表的底部(头部)插入一个节点 shift:删除一

《C#高级编程》读书笔记

<C#高级编程>读书笔记 C#类型的取值范围 名称 CTS类型 说明 范围 sbyte System.SByte 8位有符号的整数 -128~127(−27−27~27−127−1) short System.Int16 16位有符号的整数 -32 768~32 767(−215−215~215−1215−1) int System.Int32 32位有符号的整数 -2 147 483 648~2 147 483 647(−231−231~231−1231−1) long System.Int

3.2 双向链表

1.简介 前面3.1的单链表在操作过程中有一个缺点,就是后面的节点无法直接找到前面的节点,这使很多操作都得从头到尾去搜寻节点,算法效率变得非常低,解决这个问题的方法就是重新定义链表的节点使每个节点有两个指针,一个指向前驱一个指向后驱,这就是双向链表. 节点定义 template<class T> class DLLNode { public: DLLNode() { next = prev = 0; } DLLNode(const T& el, DLLNode<T> *n

《TCP/IP详解卷2:实现》笔记--IP的分片和重装

IP首部内有三个字段实现分片和重装:标识字段(ip_id).标志字段(ip_off的3个高位比特)和偏移字段(ip_off的13个低位 比特).标志字段由3个1bit标志组成.比特0是保留的必须为0,:比特1是"不分片"(DF)标志:比特2是"更多分片"(MF)标志. Net/3中,标志和偏移字段结合起来,由ip_off访问,如下图所示: ip_off的其他13bit指出在原始数据报内分片的位置,以8字节为单位计算.因此,除最后一个分片外,其他的分片都希望是一个 8

【转载】linux内核笔记之进程地址空间

原文:linux内核笔记之进程地址空间 进程的地址空间由允许进程使用的全部线性地址组成,在32位系统中为0~3GB,每个进程看到的线性地址集合是不同的. 内核通过线性区的资源(数据结构)来表示线性地址区间,线性区是由起始线性地址,长度和一些访问权限来描述的.线性区的大小为页框的整数倍,起始地址为4096的整数倍. 下图展示了x86 Linux 进程的地址空间组织结构: 正文段 .text ,这是CPU执行的机器指令部分.通常正文段是共享的,而且是只读的,以防止程序修改其自身的指令. 数据段 .d