240702任伟超8.2作业

一:单向链表(头插、删,尾插、删,遍历,按位置插入、删除,直接插入排序,链表翻转,快慢指针,释放链表)

1.main函数

 #include <stdio.h>                                                                 
 #include "./03_linklistFunc.h"                                                     
                                                                                    
 int main(int argc, const char *argv[])                                             
 {                                                                                  
     Linklist* head;                                                                
     head = create_linklist();                                                      
                                                                                    
     insert_linklistByHead(head, 100);  //100                                       
     insert_linklistByHead(head, 200);  //200 100                                   
     insert_linklistByHead(head, 300);  //300 200 100                               
     show_linklist(head);                                                           
                                                                                    
     insert_linklistByWei(head, 666);  //300 200 100 666                            
     insert_linklistByWei(head, 999);  //300 200 100 666 999                        
     show_linklist(head);                                                           
                                                                                    
     delete_linklistByHead(head);                                                   
     show_linklist(head);           //200 100 666 999                               
     delete_linklistByHead(head);                                                   
     show_linklist(head);           //100 666 999                                   
     delete_linklistByHead(head);                                                   
     show_linklist(head);           //666 999                                       
                                                                                    
     insert_linklistSort(head,777);  //666 777 999                                  
     show_linklist(head);                                                           
     insert_linklistSort(head,555);  //555 666 777 999                              
     show_linklist(head);                                                           
     insert_linklistSort(head,1111);  //555 666 777 999 1111                        
     show_linklist(head);                                                           
                                                                                    
     printf("middle num=%d\n", middleNode_linklist(head));//middle num=777          
                                                                                    
     datatype num=delete_linklistByWei(head);                                       
     show_linklist(head);           //555 666 777 999                               
     printf("num=%d\n", num);       //num=1111                                      
                                                                                    
     insert_linklistWeiZhi(head, 444, 1);                                           
     show_linklist(head);                  //444 555 666 777 999                    
     insert_linklistWeiZhi(head, 888, 5);                                           
     show_linklist(head);                 //444 555 666 777 888 999                 
     insert_linklistWeiZhi(head, 1111, 7);                                          
     show_linklist(head);                  //444 555 666 777 888 999 1111           
     insert_linklistWeiZhi(head, 2222, 9); //n=9插入位置不合法,按位置插入失败      
     insert_linklistWeiZhi(head, 222, 0);  //n=0插入位置不合法,按位置插入失败      
                                                                                    
     delete_linklistByWeiZhi(head, 0);    //=0要删除的位置不合法                    
     delete_linklistByWeiZhi(head, 1);                                              
     show_linklist(head);                 //555 666 777 888 999 1111                
     delete_linklistByWeiZhi(head, 7);    //n=7要删除的位置不合法                   
     delete_linklistByWeiZhi(head, 6);                                              
     show_linklist(head);                //555 666 777 888 999                      
                                                                                    
     fanzhuan_linklist(head);                                                       
     show_linklist(head);                //999 888 777 666 555                      
                                                                                    
     free_linklist(&head);                                                          
                                                                                    
     return 0;                                                                      
 }                                                                                  

2.头文件

#ifndef __LINKLIST__                                                       
#define __LINKLIST__                                                       
                                                                           
typedef int datatype;                                                      
typedef struct lklst                                                       
{                                                                          
    union                                                                  
    {                                                                      
        int len;           //若是头结点,则用len存储链表长度               
        datatype data;     //若是有效数据结点,则用data存放有效数据        
    }text;             //数据域                                            
                                                                           
    struct lklst* next;//指针域,指向下一个结点,存储下一个结点的首地址    
}Linklist;                                                                 
                                                                           
//创建一个空的单链表                                                       
Linklist* create_linklist(void);                                           
//头插法插入数据                                                           
void insert_linklistByHead(Linklist* head, datatype num);                  
//尾插法插入数据                                                           
void insert_linklistByWei(Linklist* head, datatype num);                   
//头删法删除数据                                                           
datatype delete_linklistByHead(Linklist* head);                            
//尾删法删除数据                                                           
datatype delete_linklistByWei(Linklist* head);                             
//遍历链表                                                                 
void show_linklist(Linklist* head);                                        
//按位置插入                                                               
void insert_linklistWeiZhi(Linklist* head, datatype num, int n);           
//按位置删除                                                               
void delete_linklistByWeiZhi(Linklist* head, int n);                       
//直接插入排序(升序)                                                     
void insert_linklistSort(Linklist* head, datatype num);                    
//链表翻转                                                                 
void fanzhuan_linklist(Linklist* head);                                    
//寻找中间结点(快慢指针)                                                   
datatype middleNode_linklist(Linklist* head);                              
//释放链表                                                                 
void free_linklist(Linklist** phead);                                      
#endif                                                                     

3.功能函数

#include <stdio.h>
#include <stdlib.h>
#include "./03_linklistFunc.h"


//创建一个空的单链表
Linklist* create_linklist(void)
{
    //在堆空间中申请了头结点的空间,头结点的首地址存储在head指针中
    //head指针就是头指针
    Linklist* head = (Linklist*)malloc(sizeof(Linklist));
    if(NULL == head)
    {
        printf("创建单链表失败\n");
        return NULL;
    }
    //初始化头结点中的len
    head->text.len = 0;
    head->next = NULL;

    return head;
}


//头插法插入数据
void insert_linklistByHead(Linklist* head, datatype num)
{
    //创建一个新的结点temp
    Linklist* temp = (Linklist*)malloc(sizeof(Linklist));                   
    if(NULL == temp)
    {
        printf("创建结点失败,头插失败\n");
        return ;
    }
    temp->text.data = num;       //数据域赋值
    temp->next = NULL;      //指针域赋值

    //将temp头插法插入链表
    temp->next = head->next;
    head->next = temp;

    //更新头结点中链表的长度
    head->text.len++;

    return ;
}

//尾插
void insert_linklistByWei(Linklist* head, datatype num)
{
    //创建一个新的结点temp  
    Linklist* temp = (Linklist*)malloc(sizeof(Linklist));
    if(NULL == temp)
    {
        printf("创建结点失败,尾插失败\n");
        return ;
    }
    temp->text.data = num;       //数据域赋值
    temp->next = NULL;      //指针域赋值

    //找尾结点p的位置:循环判断p->next是否为NULL
    Linklist* p=head;
    while(NULL != p->next)
    {
        p=p->next;
    }

    //将temp尾插法插入链表
    temp->next=NULL;      //或者temp->next=p->next;
    p->next=temp;
    //更新头结点中链表的长度
    head->text.len++;

    return ;
}
                                                                   
//头删                                                             
datatype delete_linklistByHead(Linklist* head)                     
{                                                                  
                                                                   
    //先判断链表是否为NULL                                         
    if(NULL == head->next)                                         
    {                                                              
        printf("链表为空,头删除失败\n");                          
    }                                                              
    //备份要释放的结点地址                                         
    Linklist* temp =head->next;                                    
    //修改head指针域中的地址,为要释放的结点的后一个结点的地址     
    head->next=temp->next;   //或者head->next = head->next->next;  
    //保存要释放的结点数据域中存储的数据,作为验证                 
    datatype num = temp->text.data;                                
    //释放结点,防止temp变野指针,指向NULL                         
    free(temp);                                                    
    temp=NULL;                                                     
    //更新头结点中链表的长度                                       
    head->text.len--;                                              
                                                                   
    return num;                                                    
}                                                                  
                                                                   
//尾删                                                             
datatype delete_linklistByWei(Linklist* head)                      
{                                                                  
    //判断链表是否为空                                             
    if(NULL == head->next)                                         
    {                                                              
        printf("链表为空,尾删失败\n");                            
        return (datatype)-1;                                       
    }                                                              
                                                                   
    //循环方式找倒数第2个结点p                                     
    Linklist* p=head;                                              
    while(p->next->next != NULL)                                   
    {                                                              
        p = p->next;                                               
    }                                                              
                                                                   
    //能运行到这里,代表p是倒数第2个结点                           
    //备份要删除结点中的数据                                       
    datatype num = p->next->text.data;                             
    //删除尾结点,即释放倒数第1个结点                              
                                                                   
    //备份要释放的结点地址                                         
    Linklist* temp = p->next;                                      
    p->next = NULL;                                                
    free(temp);                                                    
                                                                   
    //更新头结点中链表的长度                                       
    head->text.len--;                                              
                                                                   
    return num;                                                    
}                                                                  
                                                                   
//遍历链表                                                         
void show_linklist(Linklist* head)                                 
{                                                                  
    Linklist* p = head;                                            
    while(p->next != NULL)                                         
    {                                                              
        p=p->next;                                                 
        printf("%d ", p->text.data);                               
    }                                                              
    putchar(10);                                                   
                                                                   
    return ;                                                       
}                                                                  

//按位置插入                                                            
void insert_linklistWeiZhi(Linklist* head, datatype num, int n)         
{                                                                       
    //判断插入位置是否合法                                              
    if(n<1)                                                             
    {                                                                   
        printf("n=%d插入位置不合法,按位置插入失败\n", n);              
        return ;                                                        
    }                                                                   
                                                                        
    //找要插入位置的前一个结点位置                                      
    //例如:插入位置为2,则需要找到第1个位置                            
    Linklist* p=head;                                                   
    for(int i=0; i<n-1; i++)                                            
    {                                                                   
        p = p->next;                                                    
        //若在找的途中,p指向NULL,则代表插入位置非法                   
        if(NULL == p)                                                   
        {                                                               
            printf("n=%d插入位置不合法,按位置插入失败\n", n);          
            return ;                                                    
        }                                                               
    }                                                                   
    //能运行到这个位置,则代表找到了要插入位置的前一个结点位置          
                                                                        
    //创建一个新的结点temp                                              
    Linklist* temp = (Linklist*)malloc(sizeof(Linklist));               
    if(NULL == temp)                                                    
    {                                                                   
        printf("创建结点失败,尾插失败\n");                             
        return ;                                                        
    }                                                                   
    temp->text.data = num;       //数据域赋值                           
    temp->next = NULL;      //指针域赋值                                
                                                                        
    //将结点temp插入指定位置,即p结点的后一个位置                       
    temp->next = p->next;                                               
    p->next = temp;                                                     
                                                                        
    //更新头结点中链表的长度                                            
    head->text.len++;                                                   
    return ;                                                            
}                                                                       
                                                                        
                                                                    
//按位置删除                                                        
void delete_linklistByWeiZhi(Linklist* head, int n)                 
{                                                                   
    //先判断链表是否为空
    if(NULL == head->next)                                          
    {                                                               
        printf("链表为空,按位置删除失败\n");                       
        return ;                                                    
    }                                                               
    //判断要删除位置是否合法                                        
    if(n<1)
    {                                                               
        printf("n=%d要删除的位置不合法\n", n);                      
        return ;                                                    
    }                                                               
    //找到要删除的结点位置的前一个结点位置                          
    //例如:要删除位置2的结点,要找到位置1的结点                    
    //同时要判断如果p->next=NULL,则删除位置也不合法                 
    Linklist* p=head;                                               
    for(int i=0; i<n-1; i++)                                        
    {                                                               
        p = p->next;                                                
        if(NULL == p->next)                                         
        {                                                           
            printf("n=%d要删除的位置不合法\n", n);                  
            return ;                                                
        }                                                           
    }                                                               
                                                                    
    //按位置删除                                                    
    Linklist* temp = p->next;                                       
    p->next=temp->next;                                             
    free(temp);                                                     
    temp=NULL;                                                      
    //更新头结点中链表的长度                                        
    head->text.len--;                                               
                                                                    
    return ;                                                        
                                                                    
}                                                                   
                                                                    
                                                                    
//直接插入排序(升序)                                              
void insert_linklistSort(Linklist* head, datatype num)              
{                                                                   
    //创建一个新的结点temp                                          
    Linklist* temp = (Linklist*)malloc(sizeof(Linklist));           
    if(NULL == temp)                                                
    {                                                               
        printf("创建结点失败,尾插失败\n");                         
        return ;                                                    
    }                                                               
    temp->text.data = num;       //数据域赋值                       
    temp->next = NULL;      //指针域赋值                            
                                                                    
    Linklist* p=head;                                               
                                                                    
    //找要插入位置的前一个结点位置:                                
    //判断条件:当前结点的下一个结点是否大于要插入的数据num         
    while(p->next != NULL)                                          
    {                                                               
        if(num < p->next->text.data)                                
        {                                                           
            break;                                                  
        }                                                           
        p=p->next;                                                  
    }                                                               
    //插入temp数据                                                  
    temp->next=p->next;                                             
    p->next=temp;                                                   
                                                                    
    //更新头结点中链表的长度                                        
    head->text.len++;                                               
                                                                    
    return ;                                                        
}                                                                   

                                                                              
//链表翻转                                                                    
void fanzhuan_linklist(Linklist* head)                                        
{                                                                             
    Linklist* head1 = head;                                                   
    //创建一个临时链表head2                                                   
    Linklist* head2 = create_linklist();                                      
    //定义一个用于备份的结点                                                  
    Linklist* temp = NULL;                                                    
                                                                              
    //循环将head1中的结点头插入head1                                          
    while(NULL != head1->next)                                                
    {                                                                         
        //将head1的后一个结点从head1链表中分离出来                            
        //先备份head1的后一个结点                                             
        temp = head1->next;                                                   
        //将head1的下一个结点修改成temp的下一个结点                           
        head1->next = temp->next;                                             
        //将结点temp头插入head2中                                             
        temp->next = head2->next;                                             
        head2->next = temp;                                                   
    }                                                                         
                                                                              
    //用head1替换head2                                                        
    head1->next = head2->next;                                                
    //释放临时链表                                                            
    free(head2);                                                              
    head2 = NULL;                                                             
                                                                              
    return ;                                                                  
}                                                                             
                                                                              
                                                                              
//寻找中间结点(快慢指针)                                                      
datatype middleNode_linklist(Linklist* head)                                  
{                                                                             
    //若链表为空,fast和low都指向NULL                                         
    //此时fast->next会出现段错误                                              
    //先判断链表是否为空                                                      
    if(NULL == head->next)                                                    
    {                                                                         
        printf("链表为空,没有中间结点\n");                                   
        return (datatype)-1;                                                  
    }                                                                         
    //定义low、fast指向头指针                                                 
    Linklist* low;                                                            
    Linklist* fast;                                                           
    low = fast = head->next;                                                  
                                                                              
    //循环找到中间结点                                                        
    while(fast != NULL && fast->next != NULL)                                 
    {                                                                         
        low=low->next;                                                        
        fast=fast->next->next;                                                
    }                                                                         
    //结束循环后,low指向的就是中间结点位置                                   
    //返回low指向结点中存储的顺序                                             
    return low->text.data;                                                    
                                                                              
}                                                                             
                                                                              
//释放链表                                                                    
void free_linklist(Linklist** phead)                                          
{                                                                             
    //创建一个新的结点                                                        
    Linklist* temp = NULL;                                                    
    //循环头删直到链表为空:head->next=NULL                                   
    while(NULL != (*phead)->next)                                             
    {                                                                         
        temp = (*phead)->next;                                                
        (*phead)->next =temp->next;                                           
                                                                              
        free(temp);                                                           
        (*phead)->text.len--;                                                 
                                                                              
        show_linklist(*phead);                                                
    }                                                                         
    //释放头结点,将头指针置为NULL                                            
    free(*phead);                                                             
    *phead = NULL;                                                            
                                                                              
    return ;                                                                  
}                                                                             

二:单向循环链表(头插、删,尾插、删,遍历,按位置插入、删除)

1.main函数

#include <stdio.h>                                   |
#include "./06_looplinklistFunc.h"                   |
                                                     |
int main(int argc, const char *argv[])               |
{                                                    |
    Looplinklist* head = create_looplinklist();      |
    return 0;                                        |
}                                                    |
                                                     |

2.头文件

 #ifndef __LINKLIST__                                                          
 #define __LINKLIST__                                                          
                                                                               
 typedef int datatype;                                                         
 typedef struct loopll                                                         
 {                                                                             
     union{                                                                    
         int len;          //若是头结点,用len存储链表长度                     
         datatype data;    //若是有效数据结点,则用data存放有效数据            
     }text;                //数据域                                            
                                                                               
     struct loopll* next;  //指针域,指向下一个结点,存储下一个结点的首地址    
 }Looplinklist;                                                                
                                                                               
 Looplinklist* create_looplinklist(void);                                      
                                                                               
 #endif                                                                        

3.功能文件

#include <stdio.h>
#include <stdlib.h>
#include "./06_looplinklistFunc.h"

//创建一个空的单向循环链表
Looplinklist* create_looplinklist(void)
{
    Looplinklist* head = (Looplinklist*)malloc(sizeof(Looplinklist));
    if(NULL == head)
    {
        printf("创建单向循环链表失败\n");
        return NULL;
    }

    head->next = head;     //自己指向自己
    head->text.len = 0;    //将长度赋值为0

    return head;
}                                                                         
                                                                          

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值