数据结构学习笔记-03双向链表

321 阅读4分钟
#include <stdio.h>
#include "stdlib.h"

#define SUCCESS 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

#define MAX_SIZE 20 /*存储空间初始分配量*/

typedef int STATUS;
typedef int Element;

//定义结点
typedef struct Node {
    Element data;
    struct Node *pre;
    struct Node *next;
}Node;

typedef struct Node * LinkList;

//遍历打印
STATUS show(LinkList L) {
    //头结点是无效数据,所以取L->next
    LinkList temp = L->next;
    //容错判断
    if (temp == NULL) {
        printf("该链表为空");
        return ERROR;
    }
    
    while (temp) {
        printf("%d,   ",temp->data);
        temp = temp->next;
    }
    printf("\n");
    return SUCCESS;
}

//1.创建双向链表
STATUS ListCreat(LinkList *L) {
    //1.创建头结点: *L指向头结点
    *L = (LinkList)malloc(sizeof(Node));
    if (*L == NULL) {
        return ERROR;
    }
    (*L)->next = NULL;
    (*L)->pre = NULL;
    (*L)->data = -999;/*无效值定义*/
    
    
    
    //2.新增数据:for循环插入数据-尾插法
    LinkList p = *L;/*新建p,方便赋值操作*/
    for (int i = 0; i < 10; i ++) {
        //1.创建临时结点
        LinkList temp = (LinkList)malloc(sizeof(Node));
        temp->data = i;
        temp->pre = NULL;
        temp->next = NULL;
        
        //2.建立双向链表关系
        //① temp 是p的后继
        p->next = temp;
        //② temp 的前驱是p
        temp->pre = p;
        //③ p 要记录最后的结点的位置,方便下一次插入
        p = temp;
    }
    return SUCCESS;
}

//增
STATUS ListInsert(LinkList *L,int index,Element data) {
    //1.插入位置不合法,为0或负数
    if (index < -1) {
        return ERROR;
    }
    
    //2.新建结点
    LinkList temp = (LinkList)malloc(sizeof(Node));
    temp->data = data;
    
    //3.找到插入位置前一个结点
    LinkList p = *L;/*临时变量 方便操作*/
    for (int i = 1; i < index; i ++) {
        p = p->next;
    }
    
    //4.如果插入位置超过链表本身长度
    if (p == NULL) {
        return ERROR;
    }
    
    //5.判断插入位置是否为最后一位
    if (p->next == NULL) {
        p->next = temp;
        temp->pre = p;
        temp->next = NULL;
    } else {
        //先将p的next与temp的关联
        p->next->pre = temp;
        temp->next = p->next;
        
        //然后将p的与temp的关联
        p->next = temp;
        temp->pre = p;
    }
    return SUCCESS;
}

//删除
STATUS ListDelete(LinkList *L,int index,Element *e) {
    //1.删除位置不合法,为0或负数
    if (index < 1) {
        return ERROR;
    }
    
    //2.判断双向链表是否为空,如果为空则返回ERROR;
    if (*L == NULL) {
        return ERROR;
    }
    
    //3.找到删除位置前一个结点
    int k = 1;
    LinkList p = (*L);/*临时变量 方便操作*/
    while (k < index && p != NULL) {
        p = p->next;
        k++;
    }
    
    //4.如果k>i 或者 p == NULL 则返回ERROR
    if (k > index || p == NULL) {
        return ERROR;
    }
    
    //5.创建临时指针delTemp 指向要删除的结点,并将要删除的结点的data 赋值给*e,带回到main函数
    LinkList tempD = p->next;
    *e = tempD->data;
    
    //6.p->next 等于要删除的结点的下一个结点
    p->next = tempD->next;
    
    //7.如果删除结点的下一个结点不为空,则将将要删除的下一个结点的前驱指针赋值p;
    if (tempD->next !=NULL) {
        tempD->next->pre = p;
    }
    
    //8.删除tempD
    free(tempD);
    
    return SUCCESS;
}

//删除指定元素
STATUS ListDeleteVal(LinkList *L,Element data) {
    LinkList p = *L;
    //1.遍历
    while (p) {
        //2.判断当前结点的数据域和data是否相等,若相等则删除该结点
        if (p->data == data) {
            //修改被删除结点的前驱结点的后继指针,
            p->pre->next = p->next;
            
            //修改被删除结点的后继结点的前驱指针
            if (p->next != NULL) {
                p->next->pre = p->pre;
            }
            
            //释放p
            free(p);
            //退出循环
            break;
        }
        p = p->next;
    }
    return SUCCESS;
}

//改
STATUS ListChange(LinkList *L,int index,Element data) {
    //1.删除位置不合法,为0或负数
    if (index < 1) {
        return ERROR;
    }
    
    //2.判断双向链表是否为空,如果为空则返回ERROR;
    if (*L == NULL) {
        return ERROR;
    }
    
    //3.找到要修改的node
    LinkList p = (*L)->next;
    int k = 1;
    for (int i = 1; i < index && p->next != NULL; i ++) {
        p = p->next;
        k ++;
    }
    
    //4.如果位置超过链表长度,那么就不再修改
    if (k != index) {
        return ERROR;
    }
    
    p->data = data;
    
    return SUCCESS;
}

//查
STATUS ListFind(LinkList *L,int index,Element *data) {
    //1.位置不合法,为0或负数
    if (index < 1) {
        return ERROR;
    }
    
    //2.判断双向链表是否为空,如果为空则返回ERROR;
    if (*L == NULL) {
        return ERROR;
    }
    
    //3.找到要查找的node
    LinkList p = (*L)->next;
    int k = 1;
    for (int i = 1; i < index && p->next != NULL; i ++) {
        p = p->next;
        k ++;
    }
    
    //4.如果位置超过链表长度,那么就不再查找
    if (k != index) {
        return ERROR;
    }
    *data = p->data;
    
    return SUCCESS;
}

int main(int argc, const char * argv[]) {
    // insert code here...
    printf("Hello, World!\n");
    
    STATUS status;
    LinkList L;
    
    status = ListCreat(&L);
    show(L);
    
    printf("请输入插入的位置和数据:");
    Element insertData;
    int insertIndex;
    scanf("%d %d",&insertIndex,&insertData);
    status = ListInsert(&L, insertIndex, insertData);
    show(L);

    printf("请输入删除的位置:\n");
    Element deleteData;
    int deleteIndex;
    scanf("%d",&deleteIndex);
    status = ListDelete(&L, deleteIndex, &deleteData);
    show(L);

    printf("请输入你要删除的内容\n");
    scanf("%d",&deleteData);
    status = ListDeleteVal(&L, deleteData);
    printf("删除指定data域等于%d的结点,双向链表:\n",deleteData);
    show(L);
    
    ListChange(&L, 11, 20);
    show(L);
    
    ListChange(&L, 2, 99);
    show(L);
    
    Element findData;
    ListFind(&L, 5, &findData);
    printf("位置%d对应的数据是:%d\n",5,findData);
    
    Element findData1;
    ListFind(&L, 22, &findData1);
    printf("位置%d对应的数据是:%d\n",22,findData1);
    
    return 0;
}