双向链表

双向链表

  • 定义
  • 结构体
  • 创建一个双向链表
  • 展示双向链表中的数据元素
  • 查找双向链表中指定位置的结点
  • 向双向链表中指定位置插入结点
  • 删除双向列表指定位置的的结点

1.定义

循环链表和双向链表是对单链表的改进,仍属于链存储结构


双向链表的结点包括一个数据域和两个指针域,后继指针和前继指针域


双向链表的后继链和前继首尾相连,为空双向链表,又称双向循环链表


双向链表是一种对称结构,提供了向前搜索和向后搜索两种机会,操作插入和删除操作更加便利

前驱指针结点数据后继指针

2.结构体

创建结构类型,在DoubleCs.c文件中

/*
 双向链表结构体
 */
typedef struct dnode{
    int data;
    struct  dnode *prior,*next;
}DOUBLELINKLIST;

3.创建一个双向链表

在DoubleLinkList.h写出方法声明

#include "DoubleCs.c"

/*
 创建一个双向链表
 */
DOUBLELINKLIST * createDoubleLinkList();

在DoubleLinkList.c中实现此方法


#include "DoubleLinkList.h"
#include <stdlib.h>
#include <stdio.h>

/*
 创建一个双向链表
 */
DOUBLELINKLIST * createDoubleLinkList(){
    //1.创建一个头结点
    DOUBLELINKLIST * SQ;
    SQ=(DOUBLELINKLIST *) malloc(sizeof(DOUBLELINKLIST));
    SQ->data=-1;
    SQ->prior=NULL;
    SQ->next=NULL;

    //2.将其赋值给一个结点,供返回
    DOUBLELINKLIST *headDoubleLinkList=NULL;
    //3.循环添加结点
    DOUBLELINKLIST *tempNode;
    int  x=1;
    while (x<=10) {
        //3.1初始化添加的结点
        tempNode=(DOUBLELINKLIST *)malloc(sizeof(DOUBLELINKLIST));
        //3.2设置data数据
        tempNode->data=x;
        //3.3设置添加结点的前指针域值为SQ
        tempNode->prior=SQ;
        //3.4设置添加结点的后指针域值为NULL
        tempNode->next=NULL;
        //3.5设置链表的后指针域值为添加的结点
        SQ->next=tempNode;
        if(x==1){
            //这是为了保存了头结点,供后面返回
            headDoubleLinkList=SQ;
        }
        //3.6将临时结点赋给SQ,为了继续在后面继续添加(尾插入加载)
        SQ=tempNode;
        //4.数据自增
        x++;
    }
    return headDoubleLinkList;
}

在main.c中的main方法(int main(int argc, const char * argv[]) {})调用此方法,并且进行判断

#include "DoubleLinkList.h"
int main(int argc, const char * argv[]) {
    //创建一个双向链表
    printf("创建一个双向链表\n");
    DOUBLELINKLIST *createList=createDoubleLinkList();
    if(createList!=NULL){
        printf("创建双向链表成功success\n");
    }
}

打印结果:

创建一个双向链表
创建双向链表成功success

4.展示双向链表中的数据元素

在DoubleLinkList.h写出方法声明

#include "DoubleCs.c"
/*
 展示双向链表中的数据元素
 */
void showDoubleLinkList(DOUBLELINKLIST *SQ);

在DoubleLinkList.c中实现此方法


#include "DoubleLinkList.h"
#include <stdlib.h>
#include <stdio.h>

void showDoubleLinkList(DOUBLELINKLIST *SQ){
    if(SQ==NULL){
        printf("list=[链表为NULL]");
        return;
    }

    printf("list=[");
    printf("%d",SQ->data);
    while (SQ->next!=NULL) {
        SQ=SQ->next;
        printf(",%d",SQ->data);
    }
    printf("]\n");

}

在main.c中的main方法(int main(int argc, const char * argv[]) {})调用此方法,并且进行判断

#include "DoubleLinkList.h"
int main(int argc, const char * argv[]) {
    //展示链表中数据
    printf("输出双向链表数据\n");
    showDoubleLinkList(createList);
    printf("\n");
}

打印结果:

输出双向链表数据
list=[-1,1,2,3,4,5,6,7,8,9,10]

5.查找双向链表中指定位置的结点

在DoubleLinkList.h写出方法声明

#include "DoubleCs.c"
/*
 查找双向链表中指定位置的结点 
 */
DOUBLELINKLIST * findDoubleLinkListByPosition(DOUBLELINKLIST *SQ, int  position);

在DoubleLinkList.c中实现此方法


#include "DoubleLinkList.h"
#include <stdlib.h>
#include <stdio.h>
DOUBLELINKLIST * findDoubleLinkListByPosition(DOUBLELINKLIST *SQ, int  position){
    //1.保证SQ是使用的头结点指针,这样才能保证是顺序查找指定位置的节点
    if(SQ==NULL || SQ->next==NULL || position<=0){
        return NULL;
    }
    int  i=0;

    while (SQ!=NULL && position!=i) {
        i++;
        SQ=SQ->next;
    }
    return SQ;
}

在main.c中的main方法(int main(int argc, const char * argv[]) {})调用此方法,并且进行判断

#include "DoubleLinkList.h"
int main(int argc, const char * argv[]) {
   //查找双向链表中指定位置的结点
    printf("查找双向链表中指定位置的结点\n");
    DOUBLELINKLIST *findList=createDoubleLinkList();
    showDoubleLinkList(findList);
    int  findPosition=3;
    DOUBLELINKLIST *findNode=findDoubleLinkListByPosition(findList, findPosition);

    if(findNode==NULL){
        printf("list中不存在 %d 结点\n",findPosition);
    }else{
        printf("list中已经找到 %d 位置的结点,data=%d\n",findPosition,findNode->data);
    }
    printf("\n");
}

打印结果:

查找双向链表中指定位置的结点
list=[-1,1,2,3,4,5,6,7,8,9,10]
list中已经找到 3 位置的结点,data=3

6.向双向链表中指定位置插入结点

在DoubleLinkList.h写出方法声明

#include "DoubleCs.c"


/*
 向双向链表中指定位置插入结点
 */
DOUBLELINKLIST *insterDoubleLinkListByPosition(DOUBLELINKLIST *SQ,int position,int insterData);

在DoubleLinkList.c中实现此方法


#include "DoubleLinkList.h"
#include <stdlib.h>
#include <stdio.h>
DOUBLELINKLIST *insterDoubleLinkListByPosition(DOUBLELINKLIST *SQ,int position,int insterData){
    //1.链表的头结点赋给临时结点
    DOUBLELINKLIST *temp;
    temp=SQ;
    //2.查找到指定位置的节点
    DOUBLELINKLIST *Q2=findDoubleLinkListByPosition(temp, position);
    if(Q2==NULL){
        printf("未找到第 %d 结点",position);
        printf("添加失败failure\n");

        return SQ;
    }
    //3.找到插入位置的前一个结点
    DOUBLELINKLIST *Q1=Q2->prior;
    //4.模拟插入的节点
    DOUBLELINKLIST *P=(DOUBLELINKLIST *)malloc(sizeof(DOUBLELINKLIST));
    P->data=insterData;
    P->next=NULL;
    P->prior=NULL;
    //5.操作指针,将P插入链表中
    //5.1.把P的next指针指向Q2
    P->next=Q2;
    //5.2.把Q2的priop指针指向P
    Q2->prior=P;
    //5.3.把P的prior指针指向Q1
    P->prior=Q1;
    //5.4.把Q1的next指针指向P
    Q1->next=P;

    printf("添加成功\n");
    return SQ;
}

在main.c中的main方法(int main(int argc, const char * argv[]) {})调用此方法,并且进行判断

#include "DoubleLinkList.h"
int main(int argc, const char * argv[]) {
   //向双向链表中添加数据
    printf("向双向链表中添加数据\n");
    DOUBLELINKLIST *insertList=createDoubleLinkList();
    showDoubleLinkList(insertList);

    DOUBLELINKLIST *insertSuccessList= insterDoubleLinkListByPosition(insertList,7,77);
    showDoubleLinkList(insertSuccessList);
    printf("\n");
}

打印结果:

向双向链表中添加数据
list=[-1,1,2,3,4,5,6,7,8,9,10]
添加成功
list=[-1,1,2,3,4,5,6,77,7,8,9,10]

7.删除双向列表指定位置的的结点

在DoubleLinkList.h写出方法声明

#include "DoubleCs.c"
/*
 删除双向列表指定位置的的结点
 */
DOUBLELINKLIST * deleteDoubleLinkListByPosition();

在DoubleLinkList.c中实现此方法


#include "DoubleLinkList.h"
#include <stdlib.h>
#include <stdio.h>

/*
 删除双向列表指定位置的的结点
 */
DOUBLELINKLIST * deleteDoubleLinkListByPosition(DOUBLELINKLIST *SQ,int position){

    //1.链表的头结点赋给临时结点
    DOUBLELINKLIST *temp;
    temp=SQ;
    //2.查找到指定位置的节点
    DOUBLELINKLIST *deleteNode=findDoubleLinkListByPosition(temp, position);
    if(deleteNode==NULL){
        printf("未找到第 %d 结点\n",position);
        printf("删除失败failure\n");
        return SQ;
    }
    //3.获取删除结点的前一个结点
    DOUBLELINKLIST *Q1=deleteNode->prior;

    //4.获取删除节点的后一个结点
    DOUBLELINKLIST *Q3=deleteNode->next;

    //5.操作指针,删除deleteNode结点
     //5.1.将Q1的next指针指向deleteNode的后一个结点
    Q1->next=deleteNode->next;
    //5.2.将Q3的prior的指针指向Q1
    if(Q3==NULL){
        //表示删除的是最后一个节点,则不用操作Q3的pripr指针
    }else{
        Q3->prior=deleteNode->prior;
    }
    //6.释放删除的结点deleteNode
    free(deleteNode);

    printf("删除成功success\n");

    return SQ;
}

在main.c中的main方法(int main(int argc, const char * argv[]) {})调用此方法,并且进行判断

#include "DoubleLinkList.h"
int main(int argc, const char * argv[]) {

    //删除双向链表指定位置的结点
    printf("删除双向链表指定位置的结点\n");
    DOUBLELINKLIST *deleteList=createDoubleLinkList();
    showDoubleLinkList(deleteList);

    DOUBLELINKLIST *deleteSuccessList= deleteDoubleLinkListByPosition(deleteList,6);
    showDoubleLinkList(deleteSuccessList);
    printf("\n");
    }

打印结果:

删除双向链表指定位置的结点
list=[-1,1,2,3,4,5,6,7,8,9,10]
删除成功success
list=[-1,1,2,3,4,5,7,8,9,10]


这是对双向链表的基本操作,如有改善的地方,请大家提出,互相学习和进步.如果有好的关于数据结构与算法的书籍,还往大家推荐!

源码下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值