单链表操作

单链表的基本操作


/* 

单链表分两种:有头结点和无头结点
插入单链表方式:头部插入和尾部插入,不管是头部插入还是尾部插入,步骤是:
   1) 先把新结点的next指针指向下一个结点
   2)再把前一个结点的next指向新结点
*/
#include <stdio.h>
#include <stdlib.h>

//单向链表数据结构
typedef struct LinkedList {
    int data;
    struct LinkedList *next; 
} LinkedList;

//初始化一个单链表
//头部插入结点
LinkedList * link_list_create_from_head(int * data,int length)
{
    //创建头结点(相当于哨兵结点,不存储数据)并分配空间
    LinkedList *head = (LinkedList *)malloc(sizeof(LinkedList));
    if(head == NULL)
    {
        printf("申请空间失败");
        return NULL;
    }
    //初始化链表为空链表
    head->next = NULL;

    for(int i = 0;i < length;i++)
    {
        //创建结点,并分配内存空间
        LinkedList *node = (LinkedList *)malloc(sizeof(LinkedList));
        //为结点数据域赋值
        node->data = data[i];
        //先将当前插入结点next指针指向下一个结点,即之前的head指针所指向的结点
        node->next = head->next;
        //然后再将头结点的next指向当前插入结点
        head->next = node;
    }
    
    return head;
}

//初始化一个单链表
//尾部插入结点
LinkedList * link_list_create_from_tail(int *data,int length)
{
    LinkedList *head = (LinkedList *)malloc(sizeof(LinkedList));
    if(head == NULL){
        printf("申请空间失败");
        return NULL;
    }
    //初始化链表为空
    head->next = NULL;

    //必须申明一个指向新插入结点的指针,用来标识插入新结点位置
    //开始时候p指向head结点
    LinkedList *p = head;

    for(int i=0;i<length;i++){
        LinkedList *node = (LinkedList *)malloc(sizeof(LinkedList));
        node->data = data[i];
        //由于每次插入都是最后一个,所以结点的next指针始终指向NULL
        node->next = NULL;
        //前一个结点指针就是p的next指向新结点
        p->next = node;

        //然后把指针指向新结点
        p = node;
    }
    return head;
}

//遍历单向链表
//head: 传入头结点
void print_linkedlist(LinkedList * head)
{   
    if(head == NULL)
    {
        printf("单链表为空");
    }
    //由于头结点不存储数据,故从下一个结点遍历数据
    //申明指针p,指向头结点的下一结点
    LinkedList *p = head->next;
    //循环链表,直到指针p为空
    while(p)
    {
        printf("%d ",p->data);
        //指针p循环指向下一结点
        p = p->next;
    }
}

//单链表的插入,在链表的第i个位置插入x的元素
LinkedList * link_list_insert(LinkedList *head,int pos,int x){
    LinkedList *p = head;
    //0位置是头结点,忽略
    //找到需要插入位置的前驱结点p
    for(int i=1;i<pos;i++){
        p = p->next;
    }
    LinkedList *node = (LinkedList *)malloc(sizeof(LinkedList));
    node->data = x;
    //新结点的next指向下一个结点,也就是前驱结点p指向的结点
    node->next = p->next;
    //想前驱结点重新指向新结点
    p->next = node;
    return head;
}

//单链表的删除,在链表中删除值为x的元素,每次只能删除一个结点
LinkedList * link_list_delete(LinkedList *head,int x){
    LinkedList *p = head->next;//p指针找值为x结点
    LinkedList *pre = head;//pre指针作为x节点的前驱结点
    //while主要遍历链表,找到数据为x结点的前驱结点pre
    while(p){   
        if(p->data == x){
           break; 
        }
        pre = p;
        p = p->next;
    }
    //前驱结点的next指针重新指向要删除结点的下一个结点
    pre->next = p->next;
    //释放p结点
    free(p);
    
    return head;
}

//单链表内容的修改,在链表中修改值为x的元素变为为k
LinkedList * link_list_update(LinkedList *head,int x,int k){
    LinkedList *p = head->next;//p指针找值为x结点
    //while主要遍历链表,找到数据为x结点
    while(p){ 
        if(p->data == x){
            p->data = k;
        }
        p = p->next;
    }
    return head;
}


int main(int argc,char *argv[])
{
    int data[6] = {1,2,3,4,5,6};
    LinkedList *head = link_list_create_from_head(data,6);
    print_linkedlist(head);
    printf("\n");
    LinkedList *tail = link_list_create_from_tail(data,6);
    print_linkedlist(tail);
    printf("\n");
    //在第2个位置上插入10
    // LinkedList *L = link_list_insert(tail,2,10);
    // print_linkedlist(L);
    // printf("\n");
    //删除data=10的结点
    LinkedList *L1 = link_list_delete(tail,6);
    print_linkedlist(L1);
    printf("\n");
    //更新data=10的结点
    // LinkedList *L2 = link_list_update(tail,4,44);
    // print_linkedlist(L2);
    return 0;
}
posted @ 2022-03-02 20:49  茁壮的小草  阅读(315)  评论(0编辑  收藏  举报