数据结构 -- 链表&双向链表

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表等。

相较之于单链表,双向链表在查找前驱节点时更为方便,而单向链表却需要遍历查找;而相较之于双向链表,单链表在更加节省内存空间(双向链表比单链表多定义了一个指向前驱结点的指针)。

以下为关于单链表以及双向链表的c++实现方法:

1. 单链表

#include <cstdio>
#include <cstdlib>
#include <iostream>

using namespace std;

typedef struct linkTable{
    int info;
    linkTable *next;
};

//创建链表

linkTable* createLinkTable(linkTable *node)
{
    int temp = 0;
    linkTable *head = NULL;
    linkTable *p = (linkTable*)malloc(sizeof(linkTable));
    while (1)
    {
        scanf("%d",&temp);
        if (temp != -9999)
        {
            if (head == NULL)
            {
                p->info = temp;
                p->next = NULL;
                head = p;
            }else{
                linkTable *newnode = (linkTable *)malloc(sizeof(linkTable));
                newnode->info = temp;
                newnode->next = NULL;
                p->next = newnode;
                p = p->next;
            }
        }else{
            break;
        }
    }
    return head;

}

//在链表头部插入节点

linkTable* insertToHead(linkTable *node , int val)
{
    linkTable *newnode = (linkTable*)malloc(sizeof(linkTable));
    scanf("%d",newnode->info);
    newnode->next = node;
    return newnode;
}

//在链表中间插入节点

void insertToMid(linkTable *node , int val , int pos)
{
    int count = 0;
    linkTable *newnode = (linkTable*)malloc(sizeof(linkTable));
    newnode->info = val;
    while (node->next != NULL && ++count < pos-1)
    {
        node = node->next;
    }
    newnode->next = node->next;
    node->next = newnode;
    return;
}

//插入尾部节点

void insertToTail(linkTable *node , int val)
{
    linkTable *newnode = (linkTable*)malloc(sizeof(linkTable));
    newnode->info = val;
    newnode->next = NULL;
    while (node->next != 0)
    {
        node = node->next;
    }
    node->next = newnode;
    return;
}

//显示所有节点数值

void display(linkTable *node)
{
    while (node != NULL)
    {
        printf("%d ",node->info);
        node = node->next;
    }
    return;
}

//删除起始节点

linkTable* deleteHead(linkTable *node)
{
    linkTable *tempNode = (linkTable*)malloc(sizeof(linkTable));
    tempNode = node;
    node = node->next;
    free(tempNode);
    return node;
}

//删除尾部节点

void deleteTail(linkTable *node)
{
    linkTable *tempNode = (linkTable*)malloc(sizeof(linkTable));
    while (node->next->next != NULL && node->next != NULL)
    {
        node = node->next;
    }
    tempNode = node->next;
    node->next = NULL;
    free(tempNode);
    return;
}

//搜索指定节点,并返回节点

linkTable* searchNode(linkTable *node , int val)
{
    while (node->info != val)
    {
        if (node == NULL)
        {
            printf("No element ! \n");
            return NULL;
        }
        node = node->next;
    }
    return node;
}

int main(void)
{
    linkTable *node = (linkTable*)malloc(sizeof(linkTable));
    node = createLinkTable(node);
    display(node);
    return 0;
}

2. 双向链表

#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cmath>

using namespace std;

typedef struct DLinkList{
    int info;
    DLinkList *prev;
    DLinkList *next;
};

//链表的创建

DLinkList* createDLT(void)
{
    int temp = 0;
    DLinkList *p = (DLinkList*)malloc(sizeof(DLinkList));
    DLinkList *head = NULL;
    while (1)
    {
        scanf("%d",&temp);
        if (temp != -9999)
        {
            if (head == NULL)
            {
                head = (DLinkList*)malloc(sizeof(DLinkList));
                p->info = temp;
                p->next = NULL;
                p->prev = NULL;
                head = p;
            }else{
                DLinkList *newnode = (DLinkList*)malloc(sizeof(DLinkList));
                newnode->info = temp;
                newnode->prev = p;
                newnode->next = NULL;
                p->next = newnode;
                p = p->next;
            }
        }else{
            break;
        }
    }
    return head;
}

//链表的遍历输出

void display(DLinkList *node)
{
    while (node != NULL)
    {
        printf("%d  ",node->info);
        node = node->next;
    }
    return;
}

//添加链表头节点

DLinkList* insert_Head(DLinkList *node , int val)
{
    DLinkList *newnode = (DLinkList*)malloc(sizeof(DLinkList));
    newnode->info = val;
    newnode->next = node;
    newnode->prev = NULL;
    node->prev = newnode;
    return newnode;
}

//删除链表某位置元素

void delete_Elem(DLinkList *node , int n)
{
    int count = 1;
    while (count < n && node != NULL)
    {
        node = node->next;
        count++;
    }
    if (node != NULL)
    {
        if (node->next != NULL)
        {
            node->prev->next = node->next;
            node->next->prev = node->prev;
        }else{
            node->prev->next = NULL;
        }
    }
    return;
}

int main(void)
{
    DLinkList *node = (DLinkList*)malloc(sizeof(DLinkList));
    node = createDLT();
    node = insert_Head(node,9);
    delete_Elem(node,2);
    display(node);
    return 0;
}

原文地址:https://www.cnblogs.com/PeterZ1997/p/9532153.html

时间: 2024-10-03 02:51:11

数据结构 -- 链表&双向链表的相关文章

数据结构---基本数据结构---链表---双向链表

1.动态集合 2.每个元素都是一个对象,每个对象中都有一个关键字key和两个指针pre.next,对象中还可以包含其他 卫星数据: 3.若一个元素为x,x.pre=NIL,则该元素为链表的第一个元素,称为  链表的头:   若一个元素为x,x.next=NIL,则该元素为链表的最后一个元素,称为  链表的尾:   若一个元素为x,属性x.head指向链表的第一个元素: 4.图解: 原文地址:https://www.cnblogs.com/anpeiyong/p/10249653.html

Linux内核数据结构——链表

目录 目录 简介 单向链表 双向链表 环形链表 Linux内核中的链表实现 offsetof container_of container_of 第一部分 container_of 第二部分 链表初始化 向链表中增加一个节点 删除节点 移动节点 判断链表是否为空 遍历链表 Demo测试 mlisth mlistc 执行结果 简介 最近在学习Android Binder驱动程序实现的时候,发现里面的数据结构用到了struct list_head.而我google发现struct list_head

数据结构之双向链表(包含双向循环链表)

双向(循环)链表是线性表的链式存储结构的又一种形式. 在之前已经讲述了单向链表和循环链表.相比于单向链表只能从头结点出发遍历整个链表的局限性,循环链表使得可以从任意一个结点遍历整个链表. 但是,不管单向链表也好,循环链表也罢,都只能从一个方向遍历链表,即只能查找结点的下一个结点(后继结点),而不能查找结点的上一个结点(前驱结点).鉴于上述问题,引入了双向链表.由于双向循环链表包含双向链表的所有功能操作.因此,我们只讲述双向循环链表. 与单向链表不同,双向链表的结点构造如下图所示.即一个结点由三个

I学霸官方免费教程三十六:Java数据结构之双向链表结构

数据结构之双向链表 例如:现有双向链表TwoWayLinked中存储着1,2,3,4四个元素,那么集合对象中会有4个节点A.B.C.D,由上述结构可以知道,节点A中存储着元素1和节点B:节点B中存储着元素2和节点A和节点C,节点C中存储着元素3和节点B和节点D,节点D中存储着元素4和节点C.如果现在要在元素2和3中间插入一个元素5: 过程如下: 1.创建节点E,E中存储元素5 2.将E中的上一个节点赋值为节点B 3.将B中的下一个节点修改为节点E 4.将E中的下一个节点赋值为节点C 5.将C中的

基础数据结构 链表、栈、队列

数据结构是程序设计中一个非常重要的部分,基本的数据结构包括链表.栈和队列,当然高级一点的还有树.图等,实际上链表.栈和队列都是线性表,只是在操作和表示方式上有所不同,线性表用顺序结构表示就是顺序表,用链结构表示就是链表,如果对线性表的操作加以限制,只能有在表尾进行插入和删除元素,这就变成栈了,如果只能允许元素从表尾插入,表头删除,这就变成队列了. 链表 /* * 数据结构 链表 * 链式结构 */ #include <iostream> using namespace std; enum St

数据结构链表学习

今天初步学习数据结构链表,学习过程中感觉对于指针的理解还差很多,而且对于VS的调试也不会使用,调查问题只能靠一遍一遍的梳理逻辑,效率不是一般的低下..接下来得赶紧学习下VS的使用.. 今天链表只是初步学习,写的例子也比较简单,如下: 定义链表的数据结构,只简单的定义了一个数据和一个指向后继的指针 1 struct List { 2 int num; 3 List *next; 4 }; 接下来就是链表的创建,返回一个指针地址赋给主函数中的头指针,用于之后的增删改查等等 1 List *creat

数据结构——链表的封装

链表是数据结构中最基本的线性结构,在编程中使用的频率最高,那么如何用封装思想来编写一个完整的链表操作呢?且看以下代码的实例. /*功能:演示链表的操作方法 */              /*作者: james */              /*时间: 2014.7.16 */              /*版本: v1.0 */              /*说明:使用面向对象思想封装一个链表*/ #include <stdio.h>              #include <s

数据结构链表练习题

判断题: 1.对于顺序存储的长度为N的线性表,访问结点和增加结点的时间复杂度分别对应为O(1)和O(N).T 2.若某线性表最常用的操作是存取任一指定序号的元素和在最后进行插入和删除运算,则利用顺序表存储最节省时间.T 3.在具有N个结点的单链表中,访问结点和增加结点的时间复杂度分别对应为O(1)和O(N).F 4.对于顺序存储的长度为N的线性表,删除第一个元素和插入最后一个元素的时间复杂度分别对应为O(1)和O(N).F 5.若用链表来表示一个线性表,则表中元素的地址一定是连续的.F 6.在顺

数据结构 链表_双向链表的实现与分析

双向链表的实现与分析 双向链表的组成 :1.数据成员:2.指向下一个元素的next指针:3.指向前一个元素的prev指针. 数据结构DListElmt:代表双向链表中的单个元素(节点). 数据结构DList:代表双向链表数据结构,该结构的成员同前面介绍的单链表相似. 示例1:双向链表抽象数据类型的头文件 /*dlist.h*/ #ifndef DLIST_H #define DLIST_H /*定义双向链表中的元素*/ typedef struct DListLemt_ { void *data