单链表(Singly LInked LIst)

单链表(Singly Linked List)


单链表是比较常见的链表类型。其中每个节点都有一个指向序列下一个节点的指针。这意味着,对链表执行遍历时,只能在一个方向上从头到尾的遍历;为了能够访问链表中的最后一个节点,我们需要遍历链表中的所有元素。

单链表最后一个节点的指针域通常为NULL,在遍历到这个节点时,它指定当前链表已经结束,没有其它要遍历的节点了。

单链表的实现


定义节点

节点由两个部分组成,一个部分存储本身的数据,另一部分存储序列中下一个节点所在的内存地址。为了简单表示,我们使用一个整数作为节点的数据域,节点的数据域不仅仅局限于一个数值,可以是其它复杂的数据类型。

在C语言中,节点被定义为structure.该节点中的一个节点指向同类节点的另外一个节点。

struct Node{
    int data;
    struct Node *next;
} *head=NULL;

首先使用所需变量名创建一个新的节点,我们将其称之为newNode:

struct Node *newNode;

可以使用箭头字符访问存储在此Node中的数据:

newNode->data

同样的,使用执行节点的 *next 成员访问当前序列中的下一个节点:

newNode->next

头指针节点


头指针节点用于链表的第一个节点,用于标识链表的起点,并为链表的遍历提供入口。

链表的一些运算


链表的一些基本运算包括添加节点、删除节点、修改节点等等。

创建一个空链表

在执行任何操作之前,必须创建一个空链表。创建空链表时,head变量等于NULL,head变量将被用作链表的起点。

尾插法


可以通过创建新的节点,将新的节点和数据添加到链表的末尾。
遍历到列表的末尾,然后将此数据附加到链表的末尾。

void insertAtEnd(int value){
    struct Node *newNode;
    newNode=(struct Node*)malloc(sizeof(struct Node));
    newNode->data=value;
    newNode-next=NUll;
    if (head==NUll){
        head=newNode;
    }else{
        struct Node *temp=head;
        while(temp->next!=null){
            temp=temp->next;
        }
        temp->next=newNode;
    }
    printf("\n Node 插入成功\n");
}

头插法


将新建的节点插入到链表的头部,替换头指针,并修改该节点的连接。

void isertAtBeginning(int value){
    struct Node *newNode;
    newNode=(struct Node*)malloc(sizeof(struct Node));
    newData->data=value;
    if (head==NULL){
        newNode->next=NULL;
        head=newNode;
    }else{
        newNode->next=head;
        head=newNode;
    }
    printf("在链表头部插入节点成功");
}

插入到链表的指定位置


通过循环遍历,可以将新节点插入到链表中的指定位置。创建一个新节点,然后将其插入链表的指定位置。

void insertPosition(int value,int pos){
    int i=0;
    struct Node *newNode;
    newNode=(struct Node*)malloc(sizeof(struct Node));
    newNode->data=value;
    if (head==NULL){
        newNode->next=NULL;
        head=newNode;
    }else{
        struct Node *temp=head;
        for (i=0;i<pos-1;i++){
            temp=temp->next;
        }
        newNode->next=temp->next;
        temp->net=newNode;
    }
    printf("链表插入节点成功");
}

从链表尾部删除节点


void removeEnd(){
    if (head==NULL){
        printf("链表为空");
    }else{
        struct Node *temp1=head,*temp2;
        if (head->next==NULL){
            head=NULL;
        }else{
            while(temp1->next!=NULL){
                temp2=temp1;
                temp1=temp1->next;
            }
            temp2->next=NULL;
        }
        free(temp1);
        printf("从链表结尾删除节点成功");
    }
}

从链表头部删除节点


void removeBehinning(){
    if (head==NULL){
        printf("链表为空");
    }else{
        struct Node *temp=head;
        if (head->next==NULL){
            head=NULL;
            free(temp);
        }else{
            head=temp->next;
            free(temp);
            printf("从链表头部删除节点成功");
        }
    }
}

从链表指定位置删除节点


void removePosition(int pos){
    int i,flag=1;
    if (head==NULL){
        printf("当前链表为空");
    }else{
        struct Node *temp1=head,*temp2;
        if (pos==1){
            head=temp1->next;
            free(temp1);
            printf("节点已经删除");
        }else{
            for (i=0;i<pos-1;i++){
                if (temp1 -> next != NULL) {
                 temp2 = temp1;
                 temp1 = temp1 -> next;
             }
             else {
                flag = 0;
                break;
             }
           }
           if (flag) {
               temp2 -> next = temp1->next;
               free(temp1);
               printf("\nNode deleted\n\n");
           }
           else {
               printf("删除位置错误");
           }
        }
    }
}

链表查找


通过遍历链表来查找与给定条件符合的节点。由于只能线性访问节点,因此在这种情况下只能通过线性的方式来访问节点。这就是相较于数组,链表不支持随机访问的缺点之一。

void search(int key)
{
    while (head != NULL)
    {
        if (head->data == key)
        {
            printf("找到值\n");
            return;
        }
        head = head->next;
    }
    printf("未发现值\n");
}

更多内容,欢迎关注:


在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值