链表几种常用操作回顾

本文总结了链表的基本操作,包括创建、插入、删除等,并提供详细的实现代码。适合初学者学习链表的基本概念及掌握常见操作。

============== 链表几种常用操作回顾   ==================

//***********************************
//**      链表各种操作回顾     **  
//***********************************

#include <iostream.h>

//------------------------------------------------------------------------------
//***define eare***

//------------------------------------------------------------------------------
//***varible eare***
struct Student
{
 long number;
 float score;
 Student *next;
};

Student *head;//链首指针  注意:结构体被定义成了指针类型!!

//------------------------------------------------------------------------------
//***function pro.***
Student *Create(void);     //创建链表  注意:在该结构体类型下又定义了一个指针函数!!
void ShowList(Student *head);   //打印链表

Student *Delete(Student *head,long number);      //删除链表中某结点
Student *Insert(Student *head,Student *add_node); //插入链表结点

//------------------------------------------------------------------------------
//***main code***
void main(void)
{
 Student *phead;
 //long del_node;
 Student add_node;
 //先创建并显示init的链表
 
 phead=Create();   //注意上面定义的指针函数的调用方法!!!
 ShowList(phead);
 
 //删除链表指点结点并显示modify的链表
 /*cout<<"Do you want to delete which node? please input the number:";
 cin>>del_node;
 phead=Delete(phead,del_node);
 ShowList(phead);*/

 //插入链表结点并显示modify的链表
 cout<<"please input number&score :"<<endl;
 cin>>add_node.number>>add_node.score;

 phead=Insert(phead,&add_node);
 ShowList(phead);
}

//------------------------------------------------------------------------------
//function: Create() 创建链表
//input: void
//output:
//return: Student *
//other: fzh 2006-1-19
//------------------------------------------------------------------------------
Student *Create(void)
{
 Student *pN;    //创建链表结点的指针
 Student *pEnd;    //链尾指针,用于其后插入结点指针
 pN=new Student;    //新建一个结点,准备插入链表
 cout<<"please input numer and score:/n";
 cin>>pN->number>>pN->score; //给结点赋值
 head=NULL;     //一开始链表为空
 pEnd=pN;

 while(pN->number !=0)
 {
  if(head==NULL)
   head=pN;
  else
   pEnd->next=pN;

  pEnd=pN;    //N点处
  pN=new Student;
  cout<<"please input numer and score:/n";
  cin>>pN->number>>pN->score;
 }
 pEnd->next =NULL;
 delete pN;
 return (head);
}

//------------------------------------------------------------------------------
//function: ShowList() 显示链表
//input: void
//output:
//return: Student *
//other: fzh 2006-1-19
//------------------------------------------------------------------------------

void ShowList(Student *head)
{
 cout<<"*******now the items of list is***********/n";
 while(head)
 {
  cout<<head->number<<","<<head->score <<endl;
  head=head->next;
 }

}

//------------------------------------------------------------------------------
//function: Delete() 删除链表指点结点
//input: void
//output:
//return: Student *
//other: fzh 2006-1-19
//------------------------------------------------------------------------------
Student *Delete(Student *head,long number)
{
 Student *p;
 Student *pFind;        //"哨兵"指针
 if(!head)
 {
  cout<<"/n the link table is Null!";
  return NULL;
 }
 //情况1:要删除的结点是链首
 if(head->number==number)
 {
  p=head;
  head=head->next;
  delete p;
  cout<<number<<"the head of list have been deleted"<<endl;
  return (head);
 }

 //情况2:要删除的结点在中间或链尾
 for(pFind=head;pFind->next;pFind=pFind->next)/////***
 {
  if(pFind->next->number==number)
  {
   p=pFind->next;//待删除的结点
   pFind->next=p->next;
   delete p;
   cout<<number<<" have been deleted!"<<endl;
   
   return (head);
  }
 }

 //没有这个结点
 cout<<" /n no the node ^Q^ "<<endl;
 return NULL;
}

//------------------------------------------------------------------------------
//function: Insert() 插入链表结点
//input: void
//output:
//return: Student *
//other: 1.fzh 2006-1-19
// 2.插入要求:创建链表时,结点的number是按小到大顺序排列的。
//插入后顺序一至
//------------------------------------------------------------------------------
Student *Insert(Student *head,Student *add_node)
{
 Student *pFind;        //"哨兵"指针

 //情况1:空链表
 if(!head)//(head==NULL)   空链表时,将结点置于链首
 {
  head=add_node;   //链首
  add_node->next=NULL; //链尾 
  return head;
 }
 //情况2:插到链首
 if(head->number > add_node->number)
 {
  add_node->next=head;
  head=add_node;
  return head;

 }
 //情况3:正常情况
 for(pFind=head;pFind;pFind=pFind->next)/////
 {
  if(pFind->next->number > add_node->number)//找到插入位置
  {
   add_node->next=pFind->next;
   pFind->next=add_node;
   return head;
  }
 }
 return NULL;
}

 =================   C:链表初步(8个功能) ================

//chain

#include
<stdio.h>
#include
<string.h>
#include
<malloc.h>
#define NULL 0
#define LEN sizeof(struct node)

struct node{
long num;
char name[20];
struct node *next;
}
;

struct node *creat(void); //建立链表
struct node *insert(struct node *head); //插入节点
struct node *find(struct node *head); //查找
struct node *del(struct node *head); //删除
int count(struct node *head);//计数
void list(struct node *head);//列表
struct node *conv(struct node *head); //倒序
struct node *sort(struct node *head); //排序

void main()
{
struct node *head=NULL,*p;
int i=1;
while(i)
{
   printf(
"1.CREATE 2.COUNT 3.LIST 4.INSERT 5.FIND ");
   printf(
"6.DELETE 7.CONVERT 8.SORT 其他.QUIT ");
   
if(!scanf("%d",&i))break;
   
switch(i)
   
{
   
case 1: head=creat();break;
   
case 2: printf("%d个数据 ",count(head));break;
   
case 3: list(head);break;
   
case 4if(head)head=insert(head);break;
   
case 5:
    
{
     
if(p=find(head))printf("%ld %s ",p->num,p->name);
     
else printf("找不到 ");
     
break;
    }

   
case 6:head=del(head);break;
   
case 7:head=conv(head);break;
   
case 8:head=sort(head);break;
   
default:i=0;break;
   }

}

}


struct node *creat(void//先输入的在底部,后输入的在顶部
{
struct node *q=NULL,*p;
p
=(struct node *)malloc(LEN);
scanf(
"%ld%s",&p->num,p->name);
while(p->num)
{
   
if(!q)
   
{
    p
->next=NULL;
    q
=p;
   }

   
else
   
{
    
if(q!=p)
    
{
     p
->next=q;
     q=
p;
    }

    p
=(struct node *)malloc(LEN);
    scanf(
"%ld%s",&p->num,p->name);
   }

}

return(q);
}


struct node *insert(struct node *head) //插在第一个位置
{
struct node *p;
p
=(struct node *)malloc(LEN);
scanf(
"%ld%s",&p->num,p->name);
if(p->num)
{
   p
->next=head;
   head
=p;
}

return head;
}


struct node *find(struct node *head)
{
long a;
struct node *loc=NULL;
printf(
"输入学号:");
scanf(
"%ld",&a);
if(a||head)
{
   
for(;head;head=head->next)
    
if(head->num==a)loc=head;
}

return loc;
}


struct node *del(struct node *head)
{
struct node *p,*q;
if(p=find(head)) //先查找
{
   
if(p==head)head=head->next; //删除节点在表头
   else
   
{
    
for(q=head;q->next!=p;q=q->next); //找到p前面的节点
    q->next=p->next; //删除之
   }

}

else printf("无法删除 ");
return head;
}



int count(struct node *head)
{
int z;
struct node *p;
p
=head;
for(z=0;p;z++,p=p->next);
return z;
}


void list(struct node *head)
{
struct node *p=head;
for(;p;p=p->next)printf("%ld %s ",p->num,p->name);
}



struct node *conv(struct node *head)
{
struct node *p,*q,*r;
if(head)
{
   
if(head->next)
   
{
    q
=head->next;
    r
=head->next;
    p
=head;
    p
->next=NULL;
    
while(q->next)
    
{
     r
=r->next;
     q
->next=p;
     p
=q;
     q
=r;
    }

    q
->next=p;
    
return q;
   }

   
else return head;
}

return NULL;
}


struct node *sort(struct node *head)
{
struct node *newhead=NULL,*p,*q,*q1,*q2;
if(head)
{
   p
=head;
   newhead
=(struct node *)malloc(LEN);
   q1
=newhead;
   q2
=newhead;
   newhead
->next=NULL;
   newhead
->num=p->num;
   strcpy(newhead
->name,p->name);
   p
=p->next;
   
while(p)
   
{
    q
=(struct node *)malloc(LEN);
    q
->num=p->num;
    strcpy(q
->name,p->name);
    
while((p->num>q1->num)&&(q1->next!=NULL)) //如果要插入的比当前的大且没有到达末尾,则后移
    {
     q2
=q1;
     q1
=q1->next;
    }

    
if(p->num<=q1->num) //找到位置了
    {
     
if(newhead==q1)newhead=q; //头节点的情况
     else q2->next=q;
     q
->next=q1; //链好
    }

    
else //表尾
    {
     q1
->next=q;
     q
->next=NULL;
    }

   p
=p->next;
   q1
=newhead;
   q2
=newhead;
   }

}

return newhead;
}

<think>嗯,用户之前让我介绍嵌入式软件工程师的高频面试题,现在他们又想知道面试中常问的几种常用算法。我需要先回顾一下之前提供的答案,确保这次的内容不重复,同时补充更具体的算法部分。 首先,用户可能正在准备嵌入式相关的面试,所以算法问题可能偏向基础和应用,而不是特别复杂的算法。嵌入式系统通常资源有限,更关注效率、实时性,所以常见的算法可能包括排序、查找、位操作等。 接下来,我需要考虑用户可能的真实需求。他们可能希望了解在嵌入式面试中哪些算法最常被问到,以及如何简洁有效地回答。比如,排序算法中的快速排序和归并排序可能因为效率不同而被提及,但嵌入式环境中可能更注重空间复杂度,所以可能更关注冒泡排序或者插入排序这些虽然时间复杂度高但实现简单的算法。 另外,数据结构方面,链表、队列、栈在嵌入式系统中很常见,尤其是环形缓冲区这样的实现。哈希表可能较少,因为动态内存分配受限,但如果有应用场景的话也需要提到。 还要注意用户提到的“几种常用算法”,可能需要分点回答,结构清晰。之前的回答用了分类,比如C语言基础、数据结构等,这次可以按算法类型分类,比如排序、查找、字符串处理等。 用户可能也需要代码示例,尤其是嵌入式环境下常用的实现方式,比如用宏定义进行位操作,或者使用指针操作数据结构。同时,要解释算法的时间复杂度和应用场景,帮助面试者理解为何在特定情况下选择某种算法。 需要确保回答符合系统级指令,比如数学公式用$...$,独立公式用$$...$$,但算法部分可能公式较少,更多的是代码和复杂度分析。要检查LaTeX语法是否正确,比如时间复杂度应写成$O(n)$,用行内公式格式。 另外,用户可能对算法的实际应用感兴趣,比如在中断处理、内存管理中的使用。例如,环形缓冲区用于串口通信,位操作用于寄存器配置,这些实际例子能帮助用户更好地理解。 最后,总结部分要提醒用户结合项目经验,说明算法在嵌入式系统中的实际应用,这样回答更全面,帮助用户展示实际能力。</think>以下是嵌入式软件工程师面试中常见的几种算法及其核心解析,按应用场景分类整理: --- ### **一、排序算法** #### 1. **快速排序(Quick Sort)** - **核心思想**:分治法 + 基准值(pivot)分割。 - **时间复杂度**:平均 $O(n \log n)$,最坏 $O(n^2)$(优化后避免)。 - **代码片段**: ```c void quick_sort(int arr[], int low, int high) { if (low < high) { int pi = partition(arr, low, high); quick_sort(arr, low, pi - 1); quick_sort(arr, pi + 1, high); } } int partition(int arr[], int low, int high) { int pivot = arr[high]; int i = low - 1; for (int j = low; j < high; j++) { if (arr[j] < pivot) { i++; swap(&arr[i], &arr[j]); } } swap(&arr[i + 1], &arr[high]); return i + 1; } ``` #### 2. **归并排序(Merge Sort)** - **特点**:稳定排序,适合链表结构,空间复杂度 $O(n)$。 - **嵌入式应用**:内存充足时处理大数据排序。 --- ### **二、查找算法** #### 1. **二分查找(Binary Search)** - **前提**:有序数组。 - **时间复杂度**:$O(\log n)$。 - **代码片段**: ```c int binary_search(int arr[], int l, int r, int target) { while (l <= r) { int mid = l + (r - l) / 2; if (arr[mid] == target) return mid; if (arr[mid] < target) l = mid + 1; else r = mid - 1; } return -1; } ``` #### 2. **哈希表(Hash Table)** - **核心思想**:键值映射,冲突解决(链地址法/开放寻址法)。 - **嵌入式限制**:需避免动态内存分配,可预分配固定大小哈希表。 --- ### **三、字符串处理算法** #### 1. **KMP算法** - **用途**:高效字符串匹配(时间复杂度 $O(n+m)$)。 - **关键点**:构建部分匹配表(Partial Match Table)。 #### 2. **反转字符串(In-place)** - **嵌入式优化**:指针操作节省内存。 ```c void reverse(char *str) { char *end = str + strlen(str) - 1; while (str < end) { char tmp = *str; *str++ = *end; *end-- = tmp; } } ``` --- ### **四、位操作算法** #### 1. **计算二进制中1的个数** - **优化方法**:Brian Kernighan算法。 ```c int count_ones(uint32_t n) { int count = 0; while (n) { n &= (n - 1); // 清除最低位的1 count++; } return count; } ``` #### 2. **位掩码(Bitmask)应用** - **场景**:配置硬件寄存器或标志位。 ```c #define ENABLE_FEATURE_A (1 << 0) #define ENABLE_FEATURE_B (1 << 1) uint32_t config_reg = 0; config_reg |= ENABLE_FEATURE_A; // 设置位 config_reg &= ~ENABLE_FEATURE_B; // 清除位 ``` --- ### **五、数据结构相关算法** #### 1. **环形缓冲区(Circular Buffer)** - **用途**:串口通信、生产者-消费者模型。 - **关键操作**: - 写入:`(head + 1) % size` - 读取:`(tail + 1) % size` #### 2. **LRU缓存算法** - **核心**:哈希表 + 双向链表,保证$O(1)$访问和插入。 - **嵌入式简化**:固定容量数组 + 时间戳(牺牲时间复杂度)。 --- ### **六、递归与分治** #### 1. **斐波那契数列(动态规划优化)** - **递归问题**:直接递归有重复计算($O(2^n)$)。 - **优化方法**:记忆化搜索或迭代法($O(n)$)。 ```c int fib(int n) { if (n <= 1) return n; int a = 0, b = 1, c; for (int i = 2; i <= n; i++) { c = a + b; a = b; b = c; } return b; } ``` --- ### **七、实际场景高频考点** 1. **内存敏感算法**:选择空间复杂度低的算法(如冒泡排序 vs 归并排序)。 2. **实时性要求**:避免算法最坏情况(如快速排序需随机化基准值)。 3. **硬件相关操作**:位运算、寄存器访问代码的原子性。 --- ### **总结** 嵌入式面试中,算法问题侧重实用性、空间/时间复杂度平衡及底层优化能力。建议熟练掌握: - 基础排序/查找算法 - 位操作与内存管理技巧 - 环形缓冲区、状态机等嵌入式特有模式 回答时需结合硬件资源限制(如避免动态内存分配),并举例说明实际项目中的应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值