双向链表以及双向循环链表操作

406 阅读5分钟

双向链表

  • 双向结点构建:结点结构

    #pragma mark - 定义结点
    typedef struct Node{
        struct Node *prior;
        struct Node *next;
        ElemType data;
    }Node;
    typedef struct Node *ModelList;
    
  • 初始化双向链表

    #pragma mark - 创建双向链表
    Status InitModelList(ModelList *list){
        *list = (ModelList)malloc(sizeof(Node));
        if (!list) {
            return ERROR;
        }
        (*list)->next = NULL;
        (*list)->prior = NULL;
        //注意头结点的data可以不用赋值
        (*list)->data = -1;
        
        //增加结点
        ModelList p = *list;
        int type;
        printf("输入结点的值,输入0则结束:\n");
        while (1) {
            scanf("%d",&type);
            if (type == 0) {
                return OK;
            }
            //创建临时结点
            ModelList temp = (ModelList)malloc(sizeof(Node));
            temp->data = type;
            temp->next = NULL;
            temp->prior = NULL;
            //为临时结点建立关系
            p->next = temp;
            temp->prior = p;
            p = temp;
        }
        
            return OK;
    }
  • 双向链表的遍历

    #pragma mark - 遍历双向链表
    Status TraversalList(ModelList list){
        if (!list) {
            return ERROR;
        }
        printf("遍历双向链表开始:\n");
        //除去头结点
        ModelList temp = list->next;
        while (temp) {
            printf("%d\n",temp->data);
            temp = temp->next;
        }
        printf("遍历双向链表结束:\n");
        return OK;
    }
    
  • 双向链表的插入:图示

    需要注意的是插入时要区分是否是尾结点,因为尾结点的next-next = NULL;另一个就是插入时先处理插入位置后面结点再处理前面的结点

    #pragma mark - 双向链表插入
    Status InsertList(ModelList *list, int index, ElemType data){
        if (!list) {
            return ERROR;
        }
        ModelList p = *list;
        ModelList temp = (ModelList)malloc(sizeof(Node));
        if (!temp) {
            return ERROR;
        }
        temp->data = data;
        temp->next = NULL;
        temp->prior = NULL;
        //找到插入位置的前一个位置
        for (int i = 1; i<index && p; i++) {
            p = p->next;
        }
        //如果没有找到插入的位置
        if (!p) {
            return ERROR;
        }
        //需要独立处理是否是尾结点
        if (p->next != NULL) {//插入的位置不是尾结点
            temp->next = p->next;
            temp->next->prior = temp;
            temp->prior = p;
            p->next = temp;
        }else{//如果是最后一个结点
            p->next = temp;
            temp->prior = p;
        }
        return ERROR;
    }
    
  • 双向链表的删除:图示

    #pragma mark - 双向链表的删除
    //按结点位置删除
    Status DeleteListWithIndex(ModelList *list,int index){
        if (!list) {
            return ERROR;
        }
        ModelList p = *list;
        int i = 1;
        //找到删除结点的前一个结点
        while (i<index && p) {
            p = p->next;
            i++;
        }
        if (p->next == NULL || index<i) {//没有找删除的前一个结点
            return ERROR;
        }
        //记录删除的结点
        ModelList temp = p->next;
        p->next = temp->next;
        //如果删除的不是尾结点
        if (temp->next != NULL) {
            temp->next->prior = p;
        }
        printf("删除的结点数值为:%4d",temp->data);
        free(temp);
        return OK;
    }
    
    //按结点内容删除
    Status DeleteListWithData(ModelList *list,int data){
        if (!list) {
            return ERROR;
        }
        ModelList p = *list;
        //记录删除结点的位置
        int i = 1;
        //找到删除结点的前一个结点
        while (p->next) {
            if (p->next->data == data) {
                break;
            }
            p = p->next;
            i++;
        }
        if (p->next == NULL) {//删除结点没有找到
            return ERROR;
        }
        //记录删除的结点
        ModelList temp = p->next;
        p->next = temp->next;
        //如果删除的不是尾结点
        if (temp->next != NULL) {
            temp->next->prior = p;
        }
        printf("删除的结点位置为:%4d",i);
        free(temp);
        return OK;
    }
    
    
    
  • 双向链表指定位置结点的更新

    #pragma mark - 双向链表指定位置结点数据更新
    Status UpdataList(ModelList *list, int index, ElemType data){
        if (!list || index<1) {
            return ERROR;
        }
        ModelList p = (*list)->next;
        int i = 1;
        while (i<index) {
            p = p->next;
            i++;
        }
        if (p == NULL) {//没有找到需要更新的结点
            return ERROR;
        }
        p->data = data;
        return OK;
    }
    
    

双向循环链表

  • 初始化双向循环链表

    #pragma mark - 创建双向循环链表
    Status InitModelList(ModelList *list){
        *list = (ModelList)malloc(sizeof(Node));
        if (!list) {
            return ERROR;
        }
        (*list)->next = (*list);
        (*list)->prior = (*list);
        //注意头结点的data可以不用赋值
        (*list)->data = -1;
            //增加结点
        ModelList p = *list;
        int type;
        printf("输入结点的值,输入0则结束:\n");
        while (1) {
            scanf("%d",&type);
            if (type == 0) {
                return OK;
            }
            //此处使用的是后插法
            //创建结点
            ModelList temp = (ModelList)malloc(sizeof(Node));
            temp->data = type;
            //为临时结点建立关系
            p->next = temp;
            temp->prior = p;
            temp->next = *list;
            //头结点的前驱指向新的结点
            (*list)->prior = temp;
            //将p指向新建的结点,这样p就指向了最后的结点
            p = p->next;
        }
        
            return OK;
    }
  • 遍历双向循环链表

    #pragma mark - 遍历双向循环链表
    Status TraversalList(ModelList list){
        if (!list) {
            return ERROR;
        }
        printf("遍历双循环向链表开始:\n");
        //除去头结点
        ModelList temp = list->next;
        while (temp != list) {
            printf("%d\n",temp->data);
            temp = temp->next;
        }
        printf("遍历双向循环链表结束:\n");
        return OK;
    }
    
    
  • 双向循环链表的插入

    #pragma mark - 双向循环链表插入
    Status InsertList(ModelList *list, int index, ElemType data){
        if (!list || index<1) {
            return ERROR;
        }
        ModelList temp,p;
        int i;
        p = *list;
        temp = (ModelList)malloc(sizeof(Node));
        if (!temp) {
            return ERROR;
        }
        temp->data = data;
        //找到插入的前一个结点,i<=index,如果i<index,则会导致无法插入到最后一个
        for (i = 1; p->next != *list && i<=index; p = p->next,i++) {
            
        }
        temp->next = p->next;
        temp->prior = p;
        p->next = temp;
        if (temp->next != *list) {//插入的位置不是尾结点
            temp->next->prior = temp;
        }else{
            (*list)->prior = temp;
        }
        return OK;
    }
    
    
  • 双向循环链表的删除

    #pragma mark - 双向循环链表的删除
    Status DeleteList(ModelList *list,int index){
        if (!list || index<1) {
            return ERROR;
        }
        ModelList p = *list;
        if (p->next == *list) {//如果只有头结点则直接退出
            return ERROR;
        }
        int i = 1;
        //找到删除节点的前一个结点
        while (i<index) {
            p = p->next;
            if (p->next == *list && (*list)->next == p) {//此时表明只有一个结点了,被删除的结点前一个结点就是头结点
                p = *list;
                break;
            }
            //此处双向循环链表删除没有循环一遍,只有找到需要删除的位置才会结束
            if (p != *list) {
                i++;
            }
        }
        //删除的结点
        ModelList deleTemp = p->next;
        ElemType data = deleTemp->data;
        p->next = deleTemp->next;
        deleTemp->next->prior = p;
        free(deleTemp);
        printf("删除结点的值为:%2d\n",data);
        return OK;
    }
    
    
  • 双向循环链表根据位置查找结点

#pragma mark - 双向链表根据位置查找结点
Status SearchList(ModelList *list,int index){
    if (!list) {
        return ERROR;
    }
    int i = 1;
    ModelList p = *list;
    while (i<=index) {
        p = p->next;
        if (p->next == *list && (*list)->next == p) {//此时表明只有一个结点了
            break;
        }
        //此处双向循环链表删除没有循环一遍,只有找到需要删除的位置才会结束
        if (p != *list) {
            i++;
        }
    }
    printf("结点的值为:%2d\n",p->data);
    return OK;
}