单链表的操作

单链表

单链表是什么

单链表是一种线性的链式存储结构,由多个节点组成(头结点,中间节点和尾结点),单链表的存储结构图如下:
在这里插入图片描述
来源于网页
单链表的节点是分散的,与数组不同,数组的存储结构是连续的,单链表的每个节点存储了本节点的数据和下一个节点的地址,只能单向的查找。

单链表的操作

单链表的操作主要包括,创建,增删改查,翻转,排序。

单链表的创建

单链表的创建就是创建一个头结点
这里有两种创建方式,一种是仅仅创建一个头结点,另一个是在创建有一定长度的单链表

typedef int datatype;

typedef struct node{
    datatype data;
    struct node * next;    
}listnode, * linklist;
linklist list_creat(){
    linklist H;
    if((H = (linklist)malloc(sizeof(linklist))) == NULL){
        puts("malloc failed!\n");
        return H;
    }
    H->data = 0;
    H->next = NULL;
    return H;
}

linklist list_creat2(){
    linklist H, r, p;//三个地址
    datatype value;
    //分配一个list
    if((H = (linklist)malloc(sizeof(listnode))) == NULL){
        puts("malloc failed!\n");
        return H;
    }

    H->data = 0;
    H->next = NULL;
    r = H;
    //建节点
    while(1){
        printf("input a number(-1 to exit):");
        scanf("%d", &value);
        if(value == -1){
            break;
        }
        if((p = (linklist)malloc(sizeof(linklist))) == NULL){
            puts("malloc failed!\n");
            return H;
        }
        p->data = value;
        p->next = NULL;
        r->next = p;//将新节点的地址赋给
        r = p;//写指针移动
    }
    return H;
}

单链表的增删改查

单链表的增,可以从头部插入,也可以指定位置插入。
头部插入时,只需修改头结点的next以及新节点的next进行赋值即可。
指定位置插入时,需要找到指定位置的上一个节点(单链表的特点,单向查找所致),然后修改上一个节点以及指定位置节点的next即可。

int list_head_insert(linklist H, datatype value){
    linklist p;
    if((p = (linklist)malloc(sizeof(linklist))) == NULL){
        printf("malloc failed!\n");
        return -1;
    }
    p->data = value;
    p->next = H->next;
    H->next = p;
}
int list_insert(linklist H, datatype value, int pos){
    linklist p, q;
    if(pos == 0){
        p = H;
    }
    else{
        p = list_get(H, pos-1);
    }
    if(p == NULL){
        printf("para is invalid\n");
    }
    else{
        if((q = (linklist)malloc(sizeof(listnode))) == NULL){
            printf("malloc failed\n");
            return -1;
        }
        q->data = value;
        q->next = p->next;
        p->next = q;
        return 0;
    }
}

单链表的删,可以指定位置删除或者是按值删除
指定位置删除,对于中间节点来说找到指定位置的上一个节点,再将指定位置的上一个节点和下一个节点连接(修改next)就行了。然而单链表里有个特殊的情况,头结点没有上一个节点。

int list_delete(linklist H, int pos){
    linklist p, q;
    if(pos == 0){
        p = H;
    }
    else{
        p = list_get(H, pos - 1);
    }
    if(p == NULL || p->next == NULL){
        printf("para is invalid\n");
        return -1;
    }
    else{
        q = p->next;
        p->next = q->next;
        free(q);
        q = NULL;
        return 0;
    }
}
int list_delete_value(linklist H, datatype val){
    linklist p = H, q;
    if(p->next == NULL){
        printf("linklist is NULL\n");
        return -1;
    }
    if(list_locate(p, val) == NULL){
        printf("linklist no val\n");
        return -1;
    }
    if(p->next->data == val){
        p->next = NULL;
        return 0;
    }
    while(p->next->data != val){
        p = p->next;
    }
    q = p->next;
    p->next = q->next;
    free(q);
    return 0;
}

单链表的改只需找到节点,再修改就行了。

void list_change(linklist H, datatype val_b, datatype val_a){
    linklist p;
    p = list_locate(H, val_b);
    p->data = val_a;
}

单链表的查,可以有按位置查,按值查

linklist list_get(linklist H, int pos){
    linklist p = H;
    int i = -1;
    if(pos < 0){
        puts("position is invalid:<0\n");
        return NULL;
    }

    while (p->next && i < pos){
        p = p->next;
        i++;
    }
    //pos太大或者找到pos
    if(i == pos){
        return p;
    }
    else{
        puts("position is invalid:>length\n");
        return NULL;
    }
}
linklist list_locate(linklist H, datatype value){
    linklist p = H->next;
    while (p && p->data != value){
        p = p->next;
    }
    return p;
}

单链表的翻转

单链表的翻转就是单链表的方向方向改变。先将单链表分成两部分,再从头插入

void list_reverse(linklist H){
    linklist p, q;
    p = H->next;
    H->next = NULL;
    while(p){
        q = p;
        p = p->next;
        q->next = H->next;
        H->next = q;
    }
}

单链表的排序

升序排列,分成两部分,对数据部分进行查找最值,然后赋值

void list_sort(linklist H){
    linklist p, q, r;
    p = H->next;
    H->next = NULL;
    while(p){
        q = p;
        p = p->next;
        r = H;
        while (r->next && r->next->data < q->data){
            r = r->next;
        }
        q->next = r->next;
        r->next = q;
    }
}

ile§{
q = p;
p = p->next;
r = H;
while (r->next && r->next->data < q->data){
r = r->next;
}
q->next = r->next;
r->next = q;
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值