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

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

  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.单向循环链表:频繁进行头插和尾插

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

相关推荐
恒森宇电子有限公司14 分钟前
IP5326_BZ 支持C同口输入输出的移动电源芯片 2.4A的充放电电流 支持4LED指示灯
c语言·开发语言·单片机
曙曙学编程1 小时前
stm32——NVIC,EXIT
c语言·c++·stm32·单片机·嵌入式硬件
HUST1 小时前
C语言 第三讲:分支和循环(上)
c语言·开发语言
今日待办2 小时前
Arduino Nano33 BLESense Rev2【室内空气质量检测语音识别蓝牙调光台灯】
c语言·单片机·嵌入式硬件·mcu·语音识别·ardunio·arduinonano33
战南诚2 小时前
前端开发vscode插件 - live server
ide·vscode·编辑器
这里没有酒4 小时前
[C语言] 结构体 内存对齐规则 内存大小计算
c语言·开发语言
墨抒颖 msy.plus4 小时前
[特殊字符] 从零到一:打造你的VSCode圈复杂度分析插件
ide·vscode·编辑器·插件·cursor
Miraitowa_cheems5 小时前
LeetCode算法日记 - Day 34: 二进制求和、字符串相乘
java·算法·leetcode·链表·职场和发展
今后1236 小时前
【数据结构】带哨兵位双向循环链表
数据结构·链表
Lee嘉图6 小时前
数据结构——队列(Java)
数据结构