数据结构——单向链表实现及循环链表

一.单向链表(带头节点)的任意位置插入,代码实现

  1. 定义链表的节点和表头
cpp 复制代码
//定义节点(链表的核心)
typedef int Element;
typedef struct list_node{
     Element value;
     struct list_node *next;
}ListNode;


//链表的表头
typedef struct{
    ListNode head;
    int len;
}LinkList;

2.创建链表及初始化

cpp 复制代码
#include<stdlib.h> //申请堆空间要用到的头文件
LinkList *createLinkList(){
    LinkList *linklist=(LinkList*)malloc(sizeof(LinkList)); //申请堆空间
    if(linklist==NULL){
       return NULL; //如果空,则返回NULL,停止执行下面的指令
    }
    //初始化
    linklist->len=0;
    linklist->head.value=1;  //可以根据具体的情况来修改这个值
    linklist->head.next=NULL;

3.插入元素

cpp 复制代码
/*
步骤:
1.在指定位置上插入元素,先判断pose的合法性,遍历中发现达不到pos位置,返回NULL
2.在pos位置上插入,就要找到pos-1的位置
3. pos=1 逻辑的位置上插入,就定义cnt=0就是头节点
4. pos的取值范围是[1......
*/

//不推荐这个方法,实际工作中链表的插入,推荐头插法,而不是任意位置插入
int insertLinkList(LinkList *linklist,int pos,Element e){
    int cnt=0;
    ListNode *node=&linklist->head; //node是辅助指针

    if(pos<1||pos>linklist->len+1){  //判断pos范围
       printf("insert pos invalid!\n");
       return -1;  //结束程序
     }

// 找到pos-1的位置
while(node&&cnt<-1){
    node=node->next;
    ++cnt;
   }

//node==null和pos的位置正好找到

if(node==NULL){ 
   printf("insert pos bigger than link len!\n");
   return -1;
 }

//这里的node指向待插入节点的前一个节点
LinkNode *newNode=(ListNode *)malloc(sizeof(ListNode));
if(newNode==NULL){
   return -1;
  }
  newNode->value=0;
  newNode->next=node->next;
  node->next=newNode;
  ++linkList->len;
return 0;
}
  

4.显示链表

cpp 复制代码
void showLinkList(LinkList *linklist){
   ListNode *node=linkList->head.next;
   while(node){
  //每个节点要做的事情
    printf("%d\t",node->value);
     node=node->next;
    }
   printf("\n");
}


//带头节点的单向链表测试案例

void test01(){
    LinkList *linklist=createLinkList();
     if(linklist==NULL){
        return -1;
      }
      for(int i=0;i<5;++i){
      //头插法 倒序
       insertLinkList(linklist,1,i+100);
       }
     showLinkList(linklist);

     releaseLinkList(linklist);
 }

int main(){
    test01();
    return 0;
}

二、链表倒序的方法

  1. 每个节点,进行头插法的遍历

三、删除

cpp 复制代码
int deleteLinkList(LinkList *linklist,Element e){
    //1.找到e的前一个节点
    ListNode *node=&linklist->head;
    while(node->next && (node->next->value!=e)){
       node=node->next;
    }
    if(node->next==NULL){
      printf("Not find element!\n");
      return -1;
      }
     //2.采用备份思想,实现链式删除
     ListNode *tmp=node->next;
     node->next=tmp->next;
     free(tmp);
     --linklist->len;

四、释放

cpp 复制代码
void releaseLinkList(LinkList *linklist){
     if(linklist){
        ListNode *node=&linklist->head;
        while(node->next){
          ListNode *tmp=node->next;
          node->next=tmp->next;
          free(tmp);
          --LinkList;
           }
     printf("LinkList have %d node!\n",linklist->len);
     free(linklist); //释放头节点
       }
 }

五、面试题(链表倒序)

1.先画图

2.代码部分

cpp 复制代码
//第一种方法
void reverseLinkList(LinkList *linkList){
     ListNode *node=linklist->head.next;  //大哥
     Listnode *tmp;  // 小弟
     linklist->head.next=NULL;


     while(node){
           tmp=node;
           node=node->next;
           tmp->next=linklist->head.next;
           linklist->head.next=tmp;
     }
  //第二种方法
     while(node){
         tmp=node->next;
         node->next=linklist->head.next;
         linklist->head.next=node;
         node=tmp;
     }

六、循环链表

1.遍历

cpp 复制代码
while(node!=&head){
  node=node->next;
 }

2.单向循环链表:频繁进行头插和尾插

双向循环链表:需要倒数第几个元素时用

相关推荐
Chiyamin几秒前
图算法基础
数据结构·c++·算法
小郝 小郝25 分钟前
【C语言】浮点数在内存的储存
c语言·开发语言
阿里云云原生26 分钟前
C语言 AI 通义灵码 VSCode插件安装与功能详解
c语言
0x4081 小时前
数据结构--线性表&顺序表示(上)
数据结构·笔记
似水এ᭄往昔1 小时前
【C语言】预处理(预编译)(C语言完结篇)
c语言·开发语言
愚润求学1 小时前
【C++】模板进阶
c语言·开发语言·c++·笔记·模板
ChoSeitaku2 小时前
NO.80十六届蓝桥杯备战|数据结构-字符串哈希|兔子与兔子(C++)
数据结构·蓝桥杯·哈希算法
会打莎士比亚的猴子2 小时前
VSCode使用Remote-SSH连接服务器时启动失败glibc不符合
ide·vscode·ssh
darkchink2 小时前
[LevelDB]Block系统内幕解析-元数据块(Meta Block)&元数据索引块(MetaIndex Block)&索引块(Index Block)
android·java·服务器·c语言·数据库·c++·分布式
Rinai_R2 小时前
xv6-labs-2024 lab2
c语言·操作系统·学习笔记·计算机基础·实验