线性表-LinkList(单链表)

复制代码
知识点
1:顺序存储结构需要预分配存储空间。单链表不需要分配存储空间,元素限制不受控制
2:选择顺序存储结构-线性表需要频繁查找,很少进行插入和删除操作。使用单链表结构-元素个数变化较大或者根本不知道有多大时
3:链表改不改变,应该准确理解为链表头指针地址是否改变。
增、删、改的是非头结点时,加不加&符号,原链表都会相应改变;但一旦头指针改变,没加&符号的函数会导致程序出错;
所以一般写增加、删除、插入节点的函数时,为了保证涉及到头指针的修改不出错(尤其是不带头结点的链表),都需要加上&。
链表的第一个结点明确知道是不会改变的,故头指针地址不会改变,所以不用加&。
4:
1)传值方式传参
①传地址:
在函数中如果传递的是指针,那么只能修改指针指向的内容,不能修改指针本身;如果想要修改指针本身,要么在再加一级指针,要么用引用&。
②引用传参:
引用传参往往要比值传参高效,因为它是直接将x作为参数传入进去,而少了对x进行复制这部分的开销,既然传入进去的是x,那么对x的修改肯定也生效
2)引用方式传参引用可以被理解为变量的一个别名,但这依旧是原变量,如果在函数内对该变量进行修改的话,在外部该变量也会相应被修改。
总结
在传值方式传参时,对于基本类型:函数参数为int x,调用函数传入x;对于指针:函数参数为LNode *,调用函数时传入L
在地址传递时,对于基本类型:函数参数为int *x,调用函数传入&x;对于指针:函数参数为LNode **,调用函数时传入&L。
在引用方式传参,对于基本类型:函数参数为int &x,调用函数传入x;对于指针:函数参数为LNode* &L(或LinkList &L ),调用函数时传入&L。
复制代码
typedef struct Link
{
    int elem;
    struct Link *next;//指针域
}LinkNode,*LinkList;
//以下新建节点等价
//LinkNode *tnode1 = (linkNode *)malloc(sizeof(linkNode));
//LinkList tnode = (LinkList)malloc(sizeof(linkNode));

创建头结点

LinkList createLinkListHead() {
    LinkList head = (LinkList) malloc(sizeof(LinkNode));
    head->next = NULL;
    return head;
}

带头结点的头插法

void insertHeadLinkList(LinkList head, int value) {
    LinkList node = (LinkList) malloc(sizeof(LinkNode));
    node->elem = value;
    node->next = head->next;
    head->next = node;
}

尾插法

复制代码
void insertLastLinkList(LinkList head, int value) {
    LinkList temp = head;
    while (temp->next != NULL) //找到末尾结点
        temp = temp->next;
    LinkList node = (LinkList) malloc(sizeof(LinkNode));
    node->elem = value;
    temp->next = node;
    node->next = NULL;
}
复制代码

插入指定位置

复制代码
void insertPositionLinkList(LinkList head, int position, int value) {
    if (position < 0) //-1 从末尾添加,采用尾插法
        insertLastLinkList(head,value);
    else if (position == 0) //从第一个结点插入,采用头插法
        insertHeadLinkList(head,value);
    else { //
        LinkList temp = head->next;
        while (temp != NULL && --position > 0) { //找到合适的位置结点
            temp = temp->next;
        }
        LinkList node = (LinkList) malloc(sizeof(LinkNode));
        node->elem = value;
        node->next = temp->next;
        temp->next = node;
    }
}
复制代码

 

删除指定位置节点

复制代码
void deletePositionLinkList(LinkList head, int position) {
    if (position < 0) {
        printf("指定下标值不正确\n");
        return;
    }
    LinkList node = head;
    int i = 0;
    while (!node->next || i < position) { //寻找指定下标的节点,结束循环时,i==position
        node = node->next;
        i++;
    }
    if (i == position) { //找到指定节点
        LinkList temp = node->next; //temp 是要被删除的节点
        node->next = temp->next;
        temp->next = NULL;
        printf("该位置值为%d\n",temp->elem);
        free(temp);
    } else { //没找到
        printf("没找到指定下标的值");
    }
}
复制代码

删除指定数据节点

复制代码
void deleteValueLinkList(LinkList head, int value) {
    LinkList node = head;
    while (!node->next) {
        if (node->next->elem == value)break;//找到前节点
        node = node->next;
    }
    if (node->next != NULL) { //找到要删除的节点
        LinkList temp = node->next; //temp 是要被删除的节点
        node->next = temp->next;
        temp->next = NULL;
        free(temp);
    } else {
        printf("没找到要删除的节点\n");
    }
}
复制代码

销毁链表

void destoryLinkList(LinkList head) {
    while (head->next != NULL) {
        LinkList node = head->next;
        head->next = node->next;
        free(node);
    }
}

 

posted on   Y-flower  阅读(637)  评论(0编辑  收藏  举报

编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示