数据结构3-单链表

目录

链表(Linked List)

1.单向链表(Single-Linked List)

2.单链表应用-合并有序链表

3.单链表应用-删除链表重复元素

4.单链表应用-查找链表中间节点

5.单链表应用-查找倒数第n个节点

6.单链表应用-逆置单链表


链表(Linked List)

链表通常由一连串节点组成,每个节点包含任意的实例数据(data fields)和一或两个用来指向上一个/或下一个节点的位置的链接("links")

链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。

使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。(插入去除都变得方便)但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。

1.单向链表(Single-Linked List)

单链表是链表中结构最简单的。一个单链表的节点(Node)分为两个部分,第一个部分(data)保存或者显示关于节点的信息,另一个部分存储下一个节点的地址。最后一个节点存储地址的部分指向空值。

单向链表只可向一个方向遍历,一般查找一个节点的时候需要从第一个节点开始每次访问下一个节点,一直访问到需要的位置。而插入一个节点,对于单向链表,我们只提供在链表头插入,只需要将当前插入的节点设置为头节点,next指向原头节点即可。删除一个节点,我们将该节点的上一个节点的next指向该节点的下一个节点。

1.创建链表-------》(1)创建节点(分配内存,填充数据域和指针域(NULL))   
                                     (2)将节点链接在一起

linklist.h

#ifndef LINKLIST_H__
#define LINKLIST_H__

#include <stdio.h>

//节点结构体
struct node
{
	unsigned char elem;
	struct node *next;
};  //注意;

//函数声明
void create_list(unsigned char elem);     //节点的创建
void insert_node(int pos, unsigned char elem);    // 插入节点
void delete_node(int pos);                //删除节点
void print_linklist(void);               //输出链表
int search(unsigned char elem);          //查询链表中的某个数值 
#endif

linklist.c

#include "linklist.h"
#include <stdlib.h>


struct node *head = NULL; // 头指针
struct node *tail = NULL; // 尾指针 
//节点的创建
void create_list(unsigned char elem)
{
      struct node *p = (struct node *)malloc(sizeof(struct node));
      p->elem = elem;   // 节点内容为elem
      p->next = NULL;   //刚开始节点指针为空
    
      if(head == NULL)
            head = p;          
      else
            tail->next = p;    
      tail = p;               // 更新尾节点
}


// 插入节点
void insert_node(int pos, unsigned char elem)
{
      struct node *pre; // 前趋点
      pre = head;       // 前趋点从头开始
      int i = 0;
      struct node *p = (struct node *)malloc(sizeof(struct node));  // 创建节点
      
      if(pos == 0)               //如果更新头节点
      {
             p->elem = elem;          
             p->next = head;
             head = p;
      }
      else
      { 
            while(i < pos - 1)
            {
                 pre = pre->next; //pre是一个指针,pre->next是该指针所指向结构的一个成员
                 i++;
            }  
            p->elem = elem;        //
            p->next = pre->next;
            pre->next = p; 
            
            if(p->next == NULL)  // 尾节点
                    tail = p;
      }   
}

//删除节点
void delete_node(int pos)
{
         struct node *pre, *p;  // 前趋点
         pre = head;            // 前趋点从头开始
         int i = 0;
         
         if(pos == 0)    // 头结点
         {
              head = head->next;
              free(pre);
         }
         else
         {
              while(i < pos-1)       //更新前趋点直到要删除的前一个
              {
                  pre = pre->next;
                  i++;
              }
         
              p = pre->next;
              pre->next = p->next;
              if(p->next == NULL)
                  tail = pre;
              free(p);
              
         }
}

//输出链表
void print_linklist(void)
{
        struct node *p;
        for(p = head; p; p = p->next)
                printf("%c", p->elem);
}

//查询链表中的某个数值 
int search(unsigned char elem)
{
        struct node *p;
        for(p = head; p; p = p->next)
           if(p->elem == elem)
              return 1;
        return 0;
}

main.c

#include <stdio.h>
#include "linklist.h"


int main(void)
{
         // 创建链表
	     create_list('A');
         create_list('B');
         create_list('Z');
	     create_list('X');
         print_linklist();
         printf("\n");
         //删除
         delete_node(0);
         print_linklist();
         printf("\n");
         //插入
         insert_node(2, 'Z');
         insert_node(0, 'F');
         print_linklist();
         printf("\n");
         //查询
         if(search('A'))
              printf("the elem is found\n");
         else
              printf("the elem is not found\n");
         printf("\n");
         return 0;
}

2.单链表应用-合并有序链表

链表  1      9       13     27
链表  3       5      14     81      88     95     99
合并  1        3      5       9        13      14     27     81    88       95    99

linklist.h

#ifndef LINKLIST_H__
#define LINKLIST_H__

#include <stdio.h>

extern struct node *tail;
extern struct node *head;         //main.c 也要使用 head tail
//节点结构体
struct node
{
	unsigned int elem;
	struct node *next;
};  //注意;

//函数声明
void create_list(unsigned int elem);              //节点的创建
void insert_node(int pos, unsigned int elem);     // 插入节点
void delete_node(int pos);                        //删除节点
void print_linklist(struct node *linklist_head);  //输出链表
int search(unsigned int elem);                    //查询链表中的某个数值 
#endif

linklist.c

#include "linklist.h"
#include <stdlib.h>


struct node *head = NULL; // 头指针
struct node *tail = NULL; // 尾指针 
//节点的创建
void create_list(unsigned int elem)
{
      struct node *p = (struct node *)malloc(sizeof(struct node));
      p->elem = elem;
      p->next = NULL;
    
      if(head == NULL)
            head = p;          
      else
            tail->next = p;    
      tail = p;               // 更新尾节点
}


// 插入节点
void insert_node(int pos, unsigned int elem)
{
      struct node *pre; // 前趋点
      pre = head;       // 前趋点从头开始
      int i = 0;
      struct node *p = (struct node *)malloc(sizeof(struct node));  // 创建节点
      
      if(pos == 0)  //如果更新头点节点
      {
             p->elem = elem;
             p->next = head;
             head = p;
      }
      else
      { 
            while(i < pos - 1)
            {
                  pre = pre->next;   //pre是一个指针,pre->next是该指针所指向结构的一个成员
                  i++;
            }  
            p->elem = elem;        //
            p->next = pre->next;
            pre->next = p; 
            
            if(p->next == NULL)  // 尾节点
                    tail = p;
      }   
}

//删除节点
void delete_node(int pos)
{
         struct node *pre, *p; // 前趋点
         pre = head;           // 前趋点从头开始
         int i = 0;
         
         if(pos == 0)         // 如果删除头结点
         {
              head = head->next;
              free(pre);
         }
         else
         {
              while(i < pos-1)  //更新前趋点直到要删除的前一个
              {
                  pre = pre->next;
                  i++;
              }
         
              p = pre->next;
              pre->next = p->next;
              if(p->next == NULL)   //如果删除尾节点
                  tail = pre;
              free(p);
              
         }
}

//输出链表
void print_linklist(struct node *linklist_head)   // 结构体型指针
{
        struct node *p;
        for(p = linklist_head; p; p = p->next)
                printf("%5d", p->elem);
}

//查询链表中的某个数值 
int search(unsigned int elem)
{
        struct node *p;
        for(p = head; p; p = p->next)
           if(p->elem == elem)
              return 1;
        return 0;
}

main.c

#include <stdio.h>
#include "linklist.h"


int main(void)
{ 
         //两个链表的头指针
         struct node *head1 = NULL;
         struct node *head2 = NULL;
         //结构体指针,用来遍历两个链表
         struct node *p = NULL;
         struct node *q = NULL;
         // 创建链表1
         create_list(1);
         create_list(9);
         create_list(13);
         create_list(27);
         head1 = head;
	     print_linklist(head1);
         printf("\n");
         // 创建链表2       
         head = NULL;
         create_list(3);
         create_list(5);
         create_list(14);
         create_list(81);
         create_list(88);
         create_list(95);
         create_list(99);
         head2 = head;
	     print_linklist(head2);
         printf("\n");
         //新链表
         head = NULL;
         p = head1;
         q = head2;
         while(p && q)
         {
                if(p->elem <= q->elem)
                {
                    if(head == NULL)  //head只更新一次
                          head = p;
                    else
                          tail->next = p;
                    tail = p;
                    p = p->next;
                }
                else
                {
                   if(head == NULL)  //head只更新一次
                          head = q;
                   else
                          tail->next = q;
                   tail = q;
                   q = q->next;
                }
         } 
         tail->next = p?p:q;
         print_linklist(head);
         printf("\n");
         return 0;
}

3.单链表应用-删除链表重复元素

辅助数组flag[10]:下标:要检索的内容     元素:状态(是否出现过,0代表没出现过)

元素出现次数0000000000
数组下标0123456789

linklist.h

#ifndef LINKLIST_H__
#define LINKLIST_H__

#include <stdio.h>

extern struct node *tail;
extern struct node *head;         //main.c 也要使用 head tail
//节点结构体
struct node
{
	unsigned int elem;
	struct node *next;
};  //注意;

//函数声明
void create_list(unsigned int elem);              //节点的创建
void insert_node(int pos, unsigned int elem);     // 插入节点
void delete_node(int pos);                        //删除节点
void print_linklist(struct node *linklist_head);  //输出链表
int search(unsigned int elem);                    //查询链表中的某个数值 

#endif

linklist.c

#include "linklist.h"
#include <stdlib.h>


struct node *head = NULL; // 头指针
struct node *tail = NULL; // 尾指针 
//节点的创建
void create_list(unsigned int elem)
{
      struct node *p = (struct node *)malloc(sizeof(struct node));
      p->elem = elem;
      p->next = NULL;
    
      if(head == NULL)
            head = p;          
      else
            tail->next = p;    
      tail = p;               // 更新尾节点
}


// 插入节点
void insert_node(int pos, unsigned int elem)
{
      struct node *pre; // 前趋点
      pre = head;       // 前趋点从头开始
      int i = 0;
      struct node *p = (struct node *)malloc(sizeof(struct node));  // 创建节点
      
      if(pos == 0)  //如果更新头点节点
      {
             p->elem = elem;
             p->next = head;
             head = p;
      }
      else
      { 
            while(i < pos - 1)
            {
                  pre = pre->next;   //pre是一个指针,pre->next是该指针所指向结构的一个成员
                  i++;
            }  
            p->elem = elem;        //
            p->next = pre->next;
            pre->next = p; 
            
            if(p->next == NULL)  // 尾节点
                    tail = p;
      }   
}

//删除节点
void delete_node(int pos)
{
         struct node *pre, *p; // 前趋点
         pre = head;           // 前趋点从头开始
         int i = 0;
         
         if(pos == 0)         // 如果删除头结点
         {
              head = head->next;
              free(pre);
         }
         else
         {
              while(i < pos-1)  //更新前趋点直到要删除的前一个
              {
                  pre = pre->next;
                  i++;
              }
         
              p = pre->next;
              pre->next = p->next;
              if(p->next == NULL)   //如果删除尾节点
                  tail = pre;
              free(p);
              
         }
}

//输出链表
void print_linklist(struct node *linklist_head)   // 结构体型指针
{
        struct node *p;
        for(p = linklist_head; p; p = p->next)
                printf("%5d", p->elem);
}

//查询链表中的某个数值 
int search(unsigned int elem)
{
        struct node *p;
        for(p = head; p; p = p->next)
           if(p->elem == elem)
              return 1;
        return 0;
}


//删除重复元素
void delete_repeat(struct node *head)
{
       int flag[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
       struct node *p = head;
       struct node *q = NULL;
      
       flag[p->elem] = 1;
       while(p->next != NULL)
       {
            if(flag[p->next->elem] == 0)
            {
                 flag[p->next->elem] = 1;
                 p = p->next;
            }
            else
            {
                 q = p->next;
                 p->next = q->next;
                 free(q);
            }
       }
}

main.c

#include <stdio.h>
#include "linklist.h"


int main(void)
{ 
         // 创建链表1
         create_list(1);
         create_list(2);
         create_list(3);
         create_list(4);
         create_list(5);
         create_list(6);
         
         print_linklist(head);
         printf("\n");
         delete_repeat(head);
         print_linklist(head);
         printf("\n");

         return 0;

        
}


4.单链表应用-查找链表中间节点

快慢指针的使用:快指针走两步,慢指针走一步

linklist.h

#ifndef LINKLIST_H__
#define LINKLIST_H__

#include <stdio.h>

extern struct node *tail;
extern struct node *head;         //main.c 也要使用 head tail
//节点结构体
struct node
{
	unsigned int elem;
	struct node *next;
};  //注意;

//函数声明
void create_list(unsigned int elem);              //节点的创建
void insert_node(int pos, unsigned int elem);     // 插入节点
void delete_node(int pos);                        //删除节点
void print_linklist(struct node *linklist_head);  //输出链表
int search(unsigned int elem);                    //查询链表中的某个数值 
void delete_repeat(struct node *head);            //删除重复元素
int find_mid(struct node *head);                  //查找中间节点元素
#endif

linklist.c

#include "linklist.h"
#include <stdlib.h>


struct node *head = NULL; // 头指针
struct node *tail = NULL; // 尾指针 
//节点的创建
void create_list(unsigned int elem)
{
      struct node *p = (struct node *)malloc(sizeof(struct node));
      p->elem = elem;
      p->next = NULL;
    
      if(head == NULL)
            head = p;          
      else
            tail->next = p;    
      tail = p;               // 更新尾节点
}


// 插入节点
void insert_node(int pos, unsigned int elem)
{
      struct node *pre; // 前趋点
      pre = head;       // 前趋点从头开始
      int i = 0;
      struct node *p = (struct node *)malloc(sizeof(struct node));  // 创建节点
      
      if(pos == 0)  //如果更新头点节点
      {
             p->elem = elem;
             p->next = head;
             head = p;
      }
      else
      { 
            while(i < pos - 1)
            {
                  pre = pre->next;   //pre是一个指针,pre->next是该指针所指向结构的一个成员
                  i++;
            }  
            p->elem = elem;        //
            p->next = pre->next;
            pre->next = p; 
            
            if(p->next == NULL)  // 尾节点
                    tail = p;
      }   
}

//删除节点
void delete_node(int pos)
{
         struct node *pre, *p; // 前趋点
         pre = head;           // 前趋点从头开始
         int i = 0;
         
         if(pos == 0)         // 如果删除头结点
         {
              head = head->next;
              free(pre);
         }
         else
         {
              while(i < pos-1)  //更新前趋点直到要删除的前一个
              {
                  pre = pre->next;
                  i++;
              }
         
              p = pre->next;
              pre->next = p->next;
              if(p->next == NULL)   //如果删除尾节点
                  tail = pre;
              free(p);
              
         }
}

//输出链表
void print_linklist(struct node *linklist_head)   // 结构体型指针
{
        struct node *p;
        for(p = linklist_head; p; p = p->next)
                printf("%5d", p->elem);
}

//查询链表中的某个数值 
int search(unsigned int elem)
{
        struct node *p;
        for(p = head; p; p = p->next)
           if(p->elem == elem)
              return 1;
        return 0;
}


//删除重复元素
void delete_repeat(struct node *head)
{
       int flag[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
       struct node *p = head;
       struct node *q = NULL;
      
       flag[p->elem] = 1;
       while(p->next != NULL)
       {
            if(flag[p->next->elem] == 0)
            {
                 flag[p->next->elem] = 1;
                 p = p->next;
            }
            else
            {
                 q = p->next;
                 p->next = q->next;
                 free(q);
            }
       }
}

//查找中间节点
int find_mid(struct node *head)
{
       struct node *p;
       struct node *q;
       p = q = head;
       
       while(p != NULL && p->next != NULL)
       {
            p = p->next->next;
            q = q->next; 
       }
       return q->elem;
}

main.c 

#include <stdio.h>
#include "linklist.h"


int main(void)
{ 
         // 创建链表1
         create_list(1);
         create_list(2);
         create_list(1);
         create_list(4);
         create_list(5);
         create_list(4);

         print_linklist(head);

         printf("\n");
         printf("mid = %d\n", find_mid(head));
         return 0;
}

5.单链表应用-查找倒数第n个节点

快慢指针的使用:快指针先走n-1步,然后快慢指针同时一步一步的走

linklist.h

#ifndef LINKLIST_H__
#define LINKLIST_H__

#include <stdio.h>

extern struct node *tail;
extern struct node *head;         //main.c 也要使用 head tail
//节点结构体
struct node
{
	unsigned int elem;
	struct node *next;
};  //注意;

//函数声明
void create_list(unsigned int elem);              //节点的创建
void insert_node(int pos, unsigned int elem);     // 插入节点
void delete_node(int pos);                        //删除节点
void print_linklist(struct node *linklist_head);  //输出链表
int search(unsigned int elem);                    //查询链表中的某个数值 
void delete_repeat(struct node *head);            //删除重复元素
int find_mid(struct node *head);                  //查找中间节点元素
int find_last_nth(struct node *head, int n);       //查找倒数第n个节点
#endif

linklist.c

#include "linklist.h"
#include <stdlib.h>


struct node *head = NULL; // 头指针
struct node *tail = NULL; // 尾指针 
//节点的创建
void create_list(unsigned int elem)
{
      struct node *p = (struct node *)malloc(sizeof(struct node));
      p->elem = elem;
      p->next = NULL;
    
      if(head == NULL)
            head = p;          
      else
            tail->next = p;    
      tail = p;               // 更新尾节点
}


// 插入节点
void insert_node(int pos, unsigned int elem)
{
      struct node *pre; // 前趋点
      pre = head;       // 前趋点从头开始
      int i = 0;
      struct node *p = (struct node *)malloc(sizeof(struct node));  // 创建节点
      
      if(pos == 0)  //如果更新头点节点
      {
             p->elem = elem;
             p->next = head;
             head = p;
      }
      else
      { 
            while(i < pos - 1)
            {
                  pre = pre->next;   //pre是一个指针,pre->next是该指针所指向结构的一个成员
                  i++;
            }  
            p->elem = elem;        //
            p->next = pre->next;
            pre->next = p; 
            
            if(p->next == NULL)  // 尾节点
                    tail = p;
      }   
}

//删除节点
void delete_node(int pos)
{
         struct node *pre, *p; // 前趋点
         pre = head;           // 前趋点从头开始
         int i = 0;
         
         if(pos == 0)         // 如果删除头结点
         {
              head = head->next;
              free(pre);
         }
         else
         {
              while(i < pos-1)  //更新前趋点直到要删除的前一个
              {
                  pre = pre->next;
                  i++;
              }
         
              p = pre->next;
              pre->next = p->next;
              if(p->next == NULL)   //如果删除尾节点
                  tail = pre;
              free(p);
              
         }
}

//输出链表
void print_linklist(struct node *linklist_head)   // 结构体型指针
{
        struct node *p;
        for(p = linklist_head; p; p = p->next)
                printf("%5d", p->elem);
}

//查询链表中的某个数值 
int search(unsigned int elem)
{
        struct node *p;
        for(p = head; p; p = p->next)
           if(p->elem == elem)
              return 1;
        return 0;
}


//删除重复元素
void delete_repeat(struct node *head)
{
       int flag[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
       struct node *p = head;
       struct node *q = NULL;
      
       flag[p->elem] = 1;
       while(p->next != NULL)
       {
            if(flag[p->next->elem] == 0)
            {
                 flag[p->next->elem] = 1;
                 p = p->next;
            }
            else
            {
                 q = p->next;
                 p->next = q->next;
                 free(q);
            }
       }
}

//查找中间节点
int find_mid(struct node *head)
{
       struct node *p;
       struct node *q;
       p = q = head;
       
       while(p != NULL && p->next != NULL)
       {
            p = p->next->next;
            q = q->next; 
       }
       return q->elem;
}

//查找倒数第n个节点
int find_last_nth(struct node *head, int n)
{
       int i;
       struct node *p;
       struct node *q;
       p = q = head;
       
       for(i = 0; i < n-1; i++)
            p = p->next;
       while(p->next != NULL)
       {
            p = p->next;
            q = q->next;
       }
       
       return  q->elem;
}

main.c

#include <stdio.h>
#include "linklist.h"


int main(void)
{ 
         int n;
         // 创建链表1
         create_list(1);
         create_list(2);
         create_list(3);
         create_list(4);
         create_list(5);
         create_list(6);
         create_list(7);
         create_list(8);
         create_list(9);
         create_list(10);
         create_list(11);
         create_list(12);
         
         printf("please enter the last one you want to show:");
         scanf("%d", &n);
      
         printf("the last n:%d\n", find_last_nth(head, n));
         printf("\n");

         return 0;
}

6.单链表应用-逆置单链表

linklist.h

#ifndef LINKLIST_H__
#define LINKLIST_H__

#include <stdio.h>

extern struct node *tail;
extern struct node *head;         //main.c 也要使用 head tail
//节点结构体
struct node
{
	unsigned int elem;
	struct node *next;
};  //注意;

//函数声明
void create_list(unsigned int elem);              //节点的创建
void insert_node(int pos, unsigned int elem);     // 插入节点
void delete_node(int pos);                        //删除节点
void print_linklist(struct node *linklist_head);  //输出链表
int search(unsigned int elem);                    //查询链表中的某个数值 
void delete_repeat(struct node *head);            //删除重复元素
int find_mid(struct node *head);                  //查找中间节点元素
int find_last_nth(struct node *head, int n);       //查找倒数第n个节点
void reverse_linklist(struct node *linklist_head); //逆置链表
#endif

linklist.c

#include "linklist.h"
#include <stdlib.h>


struct node *head = NULL; // 头指针
struct node *tail = NULL; // 尾指针 
//节点的创建
void create_list(unsigned int elem)
{
      struct node *p = (struct node *)malloc(sizeof(struct node));
      p->elem = elem;
      p->next = NULL;
    
      if(head == NULL)
            head = p;          
      else
            tail->next = p;    
      tail = p;               // 更新尾节点
}


// 插入节点
void insert_node(int pos, unsigned int elem)
{
      struct node *pre; // 前趋点
      pre = head;       // 前趋点从头开始
      int i = 0;
      struct node *p = (struct node *)malloc(sizeof(struct node));  // 创建节点
      
      if(pos == 0)  //如果更新头点节点
      {
             p->elem = elem;
             p->next = head;
             head = p;
      }
      else
      { 
            while(i < pos - 1)
            {
                  pre = pre->next;   //pre是一个指针,pre->next是该指针所指向结构的一个成员
                  i++;
            }  
            p->elem = elem;        //
            p->next = pre->next;
            pre->next = p; 
            
            if(p->next == NULL)  // 尾节点
                    tail = p;
      }   
}

//删除节点
void delete_node(int pos)
{
         struct node *pre, *p; // 前趋点
         pre = head;           // 前趋点从头开始
         int i = 0;
         
         if(pos == 0)         // 如果删除头结点
         {
              head = head->next;
              free(pre);
         }
         else
         {
              while(i < pos-1)  //更新前趋点直到要删除的前一个
              {
                  pre = pre->next;
                  i++;
              }
         
              p = pre->next;
              pre->next = p->next;
              if(p->next == NULL)   //如果删除尾节点
                  tail = pre;
              free(p);
              
         }
}

//输出链表
void print_linklist(struct node *linklist_head)   // 结构体型指针
{
        struct node *p;
        for(p = linklist_head; p; p = p->next)
                printf("%5d", p->elem);
}

//查询链表中的某个数值 
int search(unsigned int elem)
{
        struct node *p;
        for(p = head; p; p = p->next)
           if(p->elem == elem)
              return 1;
        return 0;
}


//删除重复元素
void delete_repeat(struct node *head)
{
       int flag[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
       struct node *p = head;
       struct node *q = NULL;
      
       flag[p->elem] = 1;
       while(p->next != NULL)
       {
            if(flag[p->next->elem] == 0)
            {
                 flag[p->next->elem] = 1;
                 p = p->next;
            }
            else
            {
                 q = p->next;
                 p->next = q->next;
                 free(q);
            }
       }
}

//查找中间节点
int find_mid(struct node *head)
{
       struct node *p;
       struct node *q;
       p = q = head;
       
       while(p != NULL && p->next != NULL)
       {
            p = p->next->next;
            q = q->next; 
       }
       return q->elem;
}

//查找倒数第n个节点
int find_last_nth(struct node *head, int n)
{
       int i;
       struct node *p;  //快指针
       struct node *q;  //慢指针
       p = q = head;
       
       for(i = 0; i < n-1; i++) //快指针先走n-1步
            p = p->next;
       while(p->next != NULL)   //只要p->next不为空,p q 就一直一起走
       {
            p = p->next;
            q = q->next;
       }
       
       return  q->elem;  
}


// 逆置链表
void reverse_linklist(struct node *linklist_head)
{
       struct node *p, *n;
       
       p = linklist_head->next;
       linklist_head->next = NULL;

       while(p->next != NULL)
       {
            n = p->next;
            p->next = linklist_head;
            linklist_head =  p;
            p = n;
       }
       p->next = linklist_head;
       linklist_head = p;
       head = linklist_head;     //给全局变量特别重要,要不无法正常输出
                                 //因为传入的实参head始终指向的原来的头,变得是形参 
                                 //linklist_head
}

main.c

#include <stdio.h>
#include "linklist.h"


int main(void)
{ 
         int n;
         // 创建链表1
         create_list(1);
         create_list(2);
         create_list(3);
         create_list(4);
         create_list(5);
         create_list(6);
         create_list(7);
         create_list(8);
         create_list(9);
         create_list(10);
         create_list(11);
         create_list(12);
         
         reverse_linklist(head);  //逆转
         print_linklist(head);    //输出显示,注意这里在Linklist.c的操作
         printf("\n");

         return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
单链表是一种常见的数据结构,它由一个或多个节点组成,每个节点包含一个数据域和一个指针域,指针域指向下一个节点。 实现单链表的查找位序算法函数需要以下步骤: 1. 定义一个指针p指向链表的头节点,并定义一个变量count,用于计数。 2. 从头节点开始,遍历链表,当p指向某个节点时,计数器count加1。 3. 如果p指向的节点的数据与目标数据相等,则返回当前的计数器count,即为目标数据的位序。 4. 如果p指向的节点不是目标数据,则将p指向下一个节点,重复步骤3。 5. 如果遍历完链表后仍未找到目标数据,则返回-1,表示未找到。 下面是C语言实现单链表查找位序算法函数的代码示例: ```c #include <stdio.h> #include <stdlib.h> // 定义单链表节点结构 typedef struct Node { int data; // 数据域 struct Node* next; // 指针域 } Node; // 查找位序的算法函数 int findPosition(Node* head, int target) { Node* p = head; // 指向头节点 int count = 0; // 计数器初始化为0 while (p != NULL) { count++; // 计数器加1 if (p->data == target) { return count; // 找到目标数据,返回当前计数器的值 } p = p->next; // 指向下一个节点 } return -1; // 遍历完链表未找到目标数据,返回-1 } int main() { // 创建链表 Node* head = (Node*)malloc(sizeof(Node)); head->data = 1; // 头节点数据为1 Node* node1 = (Node*)malloc(sizeof(Node)); node1->data = 2; Node* node2 = (Node*)malloc(sizeof(Node)); node2->data = 3; head->next = node1; node1->next = node2; node2->next = NULL; // 查找位序示例 int target = 3; // 目标数据为3 int position = findPosition(head, target); if (position != -1) { printf("目标数据 %d 的位序为 %d\n", target, position); } else { printf("未找到目标数据 %d\n", target); } // 释放链表内存 free(node2); free(node1); free(head); return 0; } ``` 在上述代码中,我们首先定义了一个指向头节点的指针p和一个计数器count,然后使用while循环遍历链表。当p指向某个节点时,计数器加1,并判断该节点的数据是否与目标数据相等。如果找到了目标数据,则返回当前计数器的值,即为目标数据的位序。如果遍历完链表仍未找到目标数据,则返回-1表示未找到。最后在主函数中演示了调用该算法函数的示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值