线性表-双向链表

269 阅读4分钟
  • 双向链表概念

    1. 概念

    双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点

    1. 结点图解
    2. 链表图解
  • 双向链表初始化

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

typedef int Status;
typedef int ElemType;

typedef struct Node {
    struct Node * prior;
    ElemType data;
    struct Node * next;
} Node;

typedef struct Node *LinkList;

//双向链表操作(含有头结点)(也可以不设置头结点,但是在插入的时候就需要多判断插入的位置是不是1  是的话需要特殊判断)
Status createLinkList(LinkList *L){
    int number;
    LinkList temp = NULL;
    LinkList target = NULL;
    printf("可输入一个数值用于插入懂啊链表,输入0跳出循环\n");
    //向链表中插入数据
    while(1){
        scanf("%d",&number);
        if(number == 0) break;
        if(*L == NULL){
            //列表是NULL
            //1.创建一个头结点
            //2.创建一个新的节点
            //3.头结点的next指向新节点
            //4.头结点的prior指向null
            //5.新节点的prior指向头结点
            //6.新节点的next指向null
            *L = (LinkList)malloc(sizeof(Node));
            if(L == NULL) exit(0);
            (*L)->next = NULL;
            (*L)->prior = NULL;
            
            temp = (LinkList)malloc(sizeof(Node));
            if(temp == NULL) exit(0);
            temp->data = number;
            temp->prior = *L;
            (*L)->next = temp;
            temp->next = NULL;
        }else{
            //列表不是NULL
            //1.创建一个新的节点
            //2.找到尾节点
            //3.新节点的next指向NULL
            //4.新节点的prior指向尾结点
            //5.尾节点的next 指向新节点
            temp = (LinkList)malloc(sizeof(Node));
            if(temp == NULL) exit(0);
            for(target = *L; target->next != NULL; target = target->next);
            temp->data = number;
            temp->prior = target;
            temp->next = NULL;
            target->next = temp;
        }
    }
    
    return OK;
}

//记录尾结点,下一次插入的时候不需要遍历查找尾结点
Status createLinkList2(LinkList *L){
    int number;
    LinkList temp = NULL;
    LinkList lastNode = NULL;
    printf("可输入一个数值用于插入懂啊链表,输入0跳出循环\n");
    while (1) {
        scanf("%d",&number);
        if(number == 0) break;
        if(*L == NULL){
            //列表是NULL
            //1.创建一个新的节点
            //2.节点的next指向NULL
            //3.节点的prior指向NULL
            //4.lastNode = *L
            *L = (LinkList)malloc(sizeof(Node));
            if(*L == NULL) exit(0);
            (*L)->data = number;
            (*L)->next = NULL;
            (*L)->prior = NULL;
            lastNode = *L;
        }else{
            //列表不是NULL
            //1.创建一个新的节点
            //2.新节点的next指向NULL
            //2.新节点的prior指向lastNode
            //3.lastNode->next 指向新节点
            //4.lastNode等于新节点
            temp = (LinkList)malloc(sizeof(Node));
            if(temp == NULL) exit(0);
            temp->data = number;
            temp->next = NULL;
            temp->prior = lastNode;
            lastNode->next = temp;
            lastNode = temp;
        }
    }
    
    return OK;
}
  • 双向链表插入

//插入元素
//1.找到插入位置的前驱节点target
//2.创建一个新节点temp并赋值
//3.temp->next指向target->next
//4.target->next->prior指向temp
//5.target->next指向temp
//6.temp->prior 指向target
Status insert(LinkList *L,int item, int place){
    if(*L == NULL) return ERROR;
    if(place < 1) return ERROR;
    LinkList temp = NULL;
    LinkList target = NULL;
    temp = (LinkList)malloc(sizeof(LinkList));
    temp->data = item;
    temp->prior = NULL;
    temp->next = NULL;
    if(temp == NULL) return ERROR;
    int i;
    for (i = 0, target = *L; i != place-1 && target != NULL; i++,target = target->next);
    if(i != place - 1) return ERROR;
    if(target == NULL) return ERROR;
    if(target->next){
        //插入位置是最后一个元素则不用修改target->next的prior指针
        //和temp的next指针
        target->next->prior = temp;
        temp->next = target->next;
    }
    target->next = temp;
    temp->prior = target;
    return OK;
}

  • 双向链表删除

//1.找到删除位置的前驱节点target
//2.创建temp指向target->next
//3.target->next指向temp->next
//4.temp->next->prior指向target
//4.free(temp)
Status delete(LinkList *L,int place){
    if(*L == NULL) return ERROR;
    if(place < 1) return ERROR;
    LinkList target = NULL;
    LinkList temp = NULL;
    int i;
    for (i = 0, target = *L; i != place-1 && target != NULL; i++,target = target->next);
    if(i != place - 1) return ERROR;
    if(target == NULL || target->next == NULL) return ERROR;
    temp = target->next;
    //如果删除的是尾结点 不需要修改temp->next 的prior结点的指向
    if(temp->next){
        temp->next->prior = target;
        target->next = temp->next;
    }else{
        target->next = NULL;
    }
    
    
    free(temp);
    return OK;
}

  • 遍历、修改、查找

//遍历列表
void traverseList(LinkList L){
    if(L == NULL) return;
    LinkList temp = L->next;
    do{
        printf("%d ",temp->data);
        temp = temp->next;
    }while (temp != NULL);
    printf("\n");
    return;
}
//修改内容
Status modify(LinkList *L, int place, ElemType e){
    if(place < 1) return ERROR;
    if(!*L) return ERROR;
    LinkList temp = NULL;
    int i = 1;
    for (temp = (*L)->next; temp != NULL; temp = temp->next) {
        if(i == place){
            temp->data = e;
            return TRUE;
        }
        i++;
    }
    return FALSE;
}
//查找内容
Status getElem(LinkList L, int place, ElemType *e){
    LinkList temp = NULL;
    int i = 1;
    for (temp = L->next; temp != NULL; temp = temp->next) {
        if(i == place){
            (*e) = temp->data;
            return OK;
        }
        i++;
    }
    return ERROR;
}