链表的基本操作

一.链表的基本概念:
链表是一种存储结构上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针连接次序实现的;
在这里插入图片描述
二.链表的几种形态:
链表的结构非常多,组合起来有8中结构:
1.单向,双向链表;
在这里插入图片描述
2.带头,不带头链表;
在这里插入图片描述
3.循环,不循环链表;
在这里插入图片描述
在实际中最常用的链表结构有两种:
无头单向不循环链表:

在这里插入图片描述
带头双向循环链表:
在这里插入图片描述
三.链表的特点:
1.任意位置插入删除的时间复杂度为O(1),没有增容,插一个开辟一个空间;以节点为单位存储,不2.支持随机访问;
3.链表的优点:更适合长度不固定,并且频繁增删的场景
(1)O(1)时间复杂度 插入/删除;
(2)相对来说,空间更高效一点;

四.无头单向不循环链表的基本操作:
Slist.h文件中的代码:

typedef  int  SlistDataType;

//设置链表中的一个节点;
typedef struct Node{
    SlistDataType value;       //表示该节点的值;
    struct Node *next;          //表示该节点的下一个节点;

} Node;

//设置一个链表的结构体;
typedef struct Slist{
   Node* first;        //表示结构体中的第一个节点;
}Slist;

1.链表头插节点:
(1)先申请一块内存空间Node*node;(2)将V赋给新的节点node;(3)更改链表的关系;

void SlistPushFront(Slist *slist, SlistDataType num){
   Node *node=(Node*)malloc(sizeof(Node));
   node->value=num;
   node->next=slist->first;
   slist->first=num;   
}

2.链表的尾插节点:
(1)先申请一块内存空间Node* node;(2)判断链表的第一个节点是否为空,如果为空则进行头插;如果不为空则判断链表的最后一个不为空的节点,然后在该节点的下一个结点进行插入;

void SlistPushBack(Slist* slist,SlistDataType num){
   Node* node=(Node*)malloc(sizeof(Node));
   node->value=num;
   if(slist->first==NULL){
      slist->first=node;
   }
   else{
      node*c=slist->first;
      while(c->next!=NULL){
         c=c->next;
      }
      c->next=node;      
}

3.链表的头删节点:
(1)判断链表是否为空;
(2)释放头节点的空间,将第二个节点的变为第一个节点;

void SlistPopFront(Slist *slist){
   assert(slist->first!=NULL);
   Node* second=slist->first->next;
   free(slist->first);
   slist->first=second;
}

4.链表的尾删结点;
(1)先申请一块内存空间Node *node;
(2)判断链表的第一个节点是不是为空;如果为空则说明申请的该节点就是链表的第一个节点;如果不为空,找原来链表的最后一个节点,然后将申请的节点放在NULL的前一个节点;

void SlistPopBack(Slist *slist,SLDataType num){
    Node* node=(Node *)malloc(sizeof(Node));
    node->value=num;
    if(slist->first==NULL){
       slist->first=node;
    }
    else{
       Node* c=slist->first;
       while(c->next!=NULL){
          c=c->next;
       }
       c->next=node;
}

5.在链表中找到某个节点的值num;

在链表中进行遍历查找;

void SlistFind(Slist *slist,SlistDataType num){
   for(Node* c=slist->first;c!=NULL;c=c->next){
      if(c->value==num){
         return c;
      }
   }
   
   return NULL; 
}

6.在一个节点的后面做插入;
(1)申请一块内存作为需要插入的结点的地址 Node * node;
(2)将V放到申请的节点中;
(3)将指定节点的下一个节点与申请到的节点的位置进行替换;

void SlistAfter(Slist*slist,Node* post,SLDataType num){
   Node* node=(Node*)malloc(sizeof(Node));
   node->value=num;
   node->next=post;
   post->next=node;
}

7.删除链表中的某个指定节点:
(1)先判断链表的第一个节点是否为空;如果为空,则直接返回return ;
(2)如果链表中的第一个数为要删除的数,则先记录原来第二个节点,释放第一个节点的空间,把第二个节点放升级为第一;
(3)如果链表中的第一数不是要删除的数,则在链表不为NULL的前提下,进行查找;该节点的下一个节点找到了,就把该结点的下下一个节点给下一个节点,释放下一个节点;

void SlistRemove(Slist *slist,SLDataType num){
   if(slist->first==NULL){
      return 0;
   }
   if(slist->first->value==num){                   //当链表的第一个节点为要删除的节点时;
      Node *second=slist->first->next;
      free(slist->first);
      slist->first=second;
   }
   else{
      Node* c=slist->first;
      while(c->next!=NULL){
         if(c->value==num){
            Node* next=c->next;
            c->next=c->next->next;
            free(c->next);
         }
         c=c->next;
      }
   }
}

8.删除节点中的所有指定的数:
(1)判断链表的第一个结点是否为NULL;
(2)判断链表的第一个结点是否是要删除的数;
(3)在链表不为空的条件下,进行转换;

void SlistRemoveAll (Slist * slist ,SlistDataType num){
         if (slist->first==NULL){
               return;
         }
          if (slist->first->value==NULL){
                Node * second=slist->first->next;
                free (slist->first);
                slist->first=second;
         }
        Node * c=slist->first;
        while (c->next !=NULL){
             if (c->next->value== num){
                   Node * next=c->next;
                   c-next=c->next->next;
                   free (next);
             }
             else {
                  c=c->next;
             }
        } 
 }
 

五.双向带头循环链表基本操作:

//设置链表的结构体:
typedef struct Node {
      int value;
      struct Node *next;
      struct Node *prev;  //表示循环后的值
}Node;

//链表的初始化:
void DListInit(Node**p){
      Node* node = (Node *)malloc(sizeof(Node));
      //node->value没有用
      //当只有一个结点的时候;相当于结点的下一个结点还是结点本身,结点循环之后还是结点本身;
      node->next = node;
      node->prev = node;
      *p = node;
}

//结点头插:4个指针要改;
void DListPushFront(Node *head, Node * node){ 
      node->next = head->next;
      node->prev = head;
      node->next->prev = node;
      head->next = node;
}

//结点尾插:
void DListPushback(Node * head, Node * node){ 
      node->next = head;
      node->prev = head->prev;
      head->prev->next = node;
      head->prev = node;
}

//在pos 的后面插入;
void DListInsertAfter(Node *pos, Node * node){
      node->next = pos->next;
      node->prev = pos;
      pos->next->prev = node;
      pos->next = node;
}

//在pos的前面进行插入;
void DListInsertBefore(Node *pos, Node* node){
      node->next = pos;
      node->prev = pos->prev;
      pos->prev->next = node;
      pos->prev = node;
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是C语言链表基本操作的代码示例: ```c #include <stdio.h> #include <stdlib.h> struct Node { int data; struct Node *next; }; struct Node* create_node(int data) { struct Node* new_node = (struct Node*) malloc(sizeof(struct Node)); new_node->data = data; new_node->next = NULL; return new_node; } void add_node(struct Node** head, int data) { struct Node* new_node = create_node(data); if (*head == NULL) { *head = new_node; return; } struct Node* current_node = *head; while (current_node->next != NULL) { current_node = current_node->next; } current_node->next = new_node; } void delete_node(struct Node** head, int data) { struct Node* current_node = *head; struct Node* prev_node = NULL; while (current_node != NULL && current_node->data != data) { prev_node = current_node; current_node = current_node->next; } if (current_node == NULL) { return; } if (prev_node == NULL) { *head = current_node->next; } else { prev_node->next = current_node->next; } free(current_node); } void print_list(struct Node* head) { struct Node* current_node = head; while (current_node != NULL) { printf("%d ", current_node->data); current_node = current_node->next; } printf("\n"); } int main() { struct Node* head = NULL; add_node(&head, 5); add_node(&head, 10); add_node(&head, 15); add_node(&head, 20); print_list(head); delete_node(&head, 15); print_list(head); delete_node(&head, 5); print_list(head); return 0; } ``` 以上是一个简单的链表实现,包括了节点创建、添加、删除以及遍历链表并打印数据的操作。请注意,这只是一个示例代码,实际应用时需要根据具体问题进行适当的修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值