单链表的基本操作以及头插法和尾插法建立单链表

单链表的基本操作以及头插法和尾插法建立单链表

本文主要关于单链表的基本操作,创建单链表,插入节点,删除节点,查找结点,清空节点,销毁节点,以及使用头插法和尾插法建立单链表,阅读大概5分钟,希望能帮到你。

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成包括元素(数据元素的映象)和指针(指示后继元素存储位置)。元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。以“结点的序列”表示线性表称作线性链表(单链表),单链表是链式存取的结构。

单链表的操作主要包括以下几种:

  1. 创建单链表:创建一个新的链表,包括初始化头指针等操作。
  2. 插入节点:在链表的头部、尾部或者指定位置插入新的节点。
  3. 删除节点:删除链表中的指定节点,包括头节点和尾节点等。
  4. 查找节点:在链表中查找指定的节点,并返回该节点的值。
  5. 遍历链表:按照一定的顺序遍历整个链表,输出每个节点的值。
  6. 清空链表:将链表中的所有节点删除,释放内存空间。
  7. 销毁链表:彻底删除链表,包括释放内存空间等操作。

这些操作是单链表的基本操作,通过这些操作可以实现单链表的各种应用,比如插入排序、查找最大值等。同时需要注意,在实际应用中需要判断指针是否为空,以避免访问非法内存地址导致程序崩溃等问题。

基本操作示例代码

//单链表的基本操作
#include<stdio.h>
#include<stdlib.h>

//节点结构体
typedef struct Node{
    int data;
    struct Node*next;
}Node;

//单链表结构体
typedef struct LinkedList{
    Node*head;
    int length;
}LinkedList;

//初始化结构体
void initLinkedList(LinkedList*list){
    list->head=NULL;
    list->length=0;
}

//在链表末尾插入节点
void insertNode(LinkedList*list ,int data){
    Node*newNode=(Node*)malloc(sizeof(Node));
    newNode->data=data;
    newNode->next=NULL;
    if(list->head==NULL){
        list->head=newNode;
    }
    else{
        Node*temp=list->head;
        while (temp->next!=NULL){
            temp=temp->next;
        }
        temp->next=newNode;
        
    }
    list->length++;

}


//销毁链表
void destroyLinkedList(LinkedList*list){
    Node*current=list->head;
    Node*next;
    while (current!=NULL){
        next=current->next;
        free(current);
        current=next;
    }
    list->head=NULL;
    list->length=0;
    
}

//清空列表
void clearLinkedList(LinkedList*list){
    destroyLinkedList(list);
    initLinkedList(list);
}

//求链表的表长
int getLength(LinkedList*list){
    return list->length;
}


//判断链表是否为空
int isEmpty(LinkedList*list){
    return list->head==NULL?1:0;
}

int main(){
    LinkedList list;
    initLinkedList(&list);

    insertNode(&list,5);
    insertNode(&list,10);
    insertNode(&list,15);
    insertNode(&list,25);

    printf("表的长度:%d\n",getLength(&list));
    printf("链表是否为空?%s\n",isEmpty(&list)?"是":"否");
    clearLinkedList(&list);
    printf("清空后链表的长度:%d\n",getLength(&list));
    printf("清空后链表是否为空?%s\n",isEmpty(&list)?"是":"否");
    return 0;
    
}

**头插法和尾插法是单链表中的两种插入方法。**

头插法是指每次将新节点插入到链表的头部,即第一个节点的之前的位置。这种方法的特点是插入操作的时间复杂度为O(1),即无论链表的大小如何,插入操作的时间复杂度都是常数时间。但是,头插法会导致链表中元素的数据顺序与插入顺序相反。

尾插法是指每次将新节点插入到链表的尾部,即最后一个节点的之后的位置。这种方法的特点是插入操作的时间复杂度为O(n),即插入操作需要遍历整个链表才能找到尾部节点。但是,尾插法可以保持链表中元素的数据顺序与插入顺序一致。

在实际应用中,可以根据具体需求选择不同的插入方法。如果需要频繁插入和删除操作,头插法可能会更合适;如果需要保持数据顺序与插入顺序一致,尾插法可能会更合适。

示例代码如下

//单链表的操作(尾插法和头插法建立单链表)
#include<stdio.h>
#include<stdlib.h>

struct Node{
    int data;
    struct Node*next;
};

//创建新节点
struct Node*createNode(int data){
    struct Node*newNode=(struct Node*)malloc(sizeof(struct Node));
    if(newNode==NULL){
        printf("内存分配失败");
        exit(1);
    }
    newNode->data=data;
    newNode->next=NULL;
    return newNode;
}

//头插法建立单链表
struct Node*insertAtBeginning(struct Node*head,int data){
    struct Node*newNode=createNode(data);
    newNode->next=head;
    return newNode;
}

//尾插法建立单链表
struct Node*insertAtEnd(struct Node*head,int data){
    struct Node*newNode=createNode(data);
    if(head==NULL){
        return newNode;
    }
    struct Node*temp=head;
    while(temp->next!=NULL){
        temp=temp->next;
    }
    temp->next=newNode;
    return head;
}

//取单链表中第i个元素
int getAtIndex(struct Node*head,int index){
    int count=0;
    struct Node*current=head;
    while(current!=NULL){
        if(count==index){
            return current->data;
        }
        count++;
        current=current->next;
    }
    printf("索引超出范围\n");
    return -1;  // 表示未找到

}

//按值查找节点位置序号
int findPosition(struct Node*head,int value){
    int pos=0;
    struct Node*current=head;
    while(current!=NULL){
        if(current->data==value){
            return pos;
        }
        pos++;
        current=current->next;
    }
    printf("未找到该值\n");
    return -1; // 表示未找到
}

//在第i个结点前插入新节点
struct Node*insertBeforeIndex(struct Node*head,int index,int data){
    if(index==0){
        return insertAtBeginning(head,data);
    }
    int count=0;
    struct Node*current=head;
    while(current!=NULL&&count<index-1){
        current=current->next;
        count++;
    }
    if(current==NULL){
        printf("索引超出范围\n");
        return head;
    }
    struct Node*newNode=createNode(data);
    newNode->next=current->next;
    current->next=newNode;
    return head;
}

//删除第i个节点
struct Node*daleteAtIndex(struct Node*head,int index){
    if(head==NULL){
        printf("链表为空\n");
        return NULL;
    }
    if(index==0){
        struct Node*temp=head;
        head=head->next;
        free(temp);
        return head;
    }
    int count=0;
    struct Node*current=head;
    struct Node*prev=NULL;
    while(current!=NULL&&count<index){
        prev=current;
        current=current->next;
        count++;
    }
    if(current==NULL){
        printf("索引超出范围\n");
        return head;
    }
    prev->next=current->next;
    free(current);
    return head;

}

//打印单链表
void printLinkedList(struct Node*head){
    struct Node*temp=head;
    while (temp!=NULL){
        printf("%d->",temp->data);
        temp=temp->next;
    }
    printf("NULL\n");
   
}

int main(){
    struct Node*head=NULL;

    //使用头插法建立单链表
    head=insertAtBeginning(head,5);
    head=insertAtBeginning(head,15);
    head=insertAtBeginning(head,25);
    head=insertAtBeginning(head,65);
    printf("头插法建立单链表以后:");
    printLinkedList(head);

    //使用尾插法建立单链表
    head=insertAtEnd(head,8);
    head=insertAtEnd(head,58);
    head=insertAtEnd(head,68);
    head=insertAtEnd(head,78);
    printf("尾插法建立单链表以后:");
    printLinkedList(head);

    //获取第i个元素
    int elementAtIndex=getAtIndex(head,2);
    printf("索引2处的元素:%d\n",elementAtIndex);

    //查找元素的位置序号
    int position=findPosition(head,58);
    printf("值为58的位置:%d\n",position);

    //在第i个结点前插入新节点
    head=insertBeforeIndex(head,3,30);
    printf("在索引3处前插入节点后:");
    printLinkedList(head);

    //删除第i个节点
    head=daleteAtIndex(head,2);
    printf("删除索引2处的节点后:");
    printLinkedList(head);
    return 0;

}

运行效果
在这里插入图片描述

感谢阅读

  • 20
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值