双循环链表的编程实现

一、实现双向循环链表

main.c

#include "loop.h"
int main(int argc, const char *argv[])
{
    node_p H=create_link();
    insert_head(H,7);
    show_node(H);
    insert_tail(H,9);
    show_node(H);
    insert_tail(H,47);
    show_node(H);
    insert_tail(H,23);
    show_node(H);
    insert_tail(H,19);
    show_node(H);
    insert_tail(H,11);
    show_node(H);
    dele_head(H);
    show_node(H);
    dele_tail(H);
    show_node(H);
    int pos=2;
    printf("%d\n",seek_pos(H,pos));
    return 0;
}

loop.c

#include "loop.h"                                  
//1、创建头结点                                    
node_p create_link()                               
{                                                  
    node_p H=(node_p)malloc(sizeof(node));         
    if(H==NULL)                                    
    {                                              
        printf("申请空间失败");                    
        return NULL ;                              
    }                                              
    H->len=0;                                      
    H->next=NULL;                                     
    H->pri=H;                                      
        return H ;                                 
}                                                  
//2、创建链表结点                                  
node_p create_node(int value)                      
{                                                  
    node_p new=(node_p)malloc(sizeof(node));       
    if(new==NULL)                                  
     {                                             
        printf("申请空间失败");                    
        return NULL ;                              
    }                                              
    new->data=value;                               
    new->pri=NULL;                                 
    new->next=NULL;                                
    return new ;                                   
}                                                  
//3、判空                                               
int empty_node(node_p H)                                
{                                                       
    if(H==NULL) {return -1;}                            
    return H->next==NULL? 1:0;                          
}                                                       
//4、头插                                               
void insert_head(node_p H,int value)                    
{                                                       
    if(H==NULL) { return ;}                             
    node_p new=create_node(value);                      
    new->pri=H;                                         
    //新结点的前驱指向头结点                            
    if(H->next!=NULL)                                   
    {                                                   
        H->next->pri=new;                               
        //头结点后驱结点的前驱指向新结点                
        new->next=H->next;                              
        //新结点的后驱指向头结点的后驱                  
    }                                                   
    else                                                
    {                                                   
        H->pri=new;                                     
        new->next=H; //新结点的后驱指向头结点的后驱     
    }                                                   
    H->next=new;                                        
    H->len++;                                           
    return ;                                            
}                                                       

//6、按位置插入
void insert_pos(node_p H,int pos,int value)
{
    if(H==NULL) { return ;}
    //判断插入位置是否合理
    if(pos<1 || pos>H->len)
    {
        printf("插入元素位置不合理\n");
        return ;
    }
    int i;
    node_p p;
    //循环找出需要插入元素的位置
    for(i=0,p=H;i<pos-1;i++,p=p->next)
    {
        //如果该位置为尾结点,则调用尾插函数
        if(p->next==NULL)
        {
            insert_tail(H,value);
            return ;
        }
    }
    node_p new=create_node(value);
    new->pri=p; //新结点的前驱指向P结点
    if(p->next!=NULL)
    {
        new->next=p->next; //新结点后驱指向p结点后驱
        p->next->pri=new;  //p结点的后驱的前驱指向新结点
    }
    else
    {
        new->next=H;
        H->pri=new;
    }
    p->next=new;  //p结点的后驱指向新结点
    H->len++;
    return ;
}
//7、头删
void dele_head(node_p H)
{
    if(H==NULL) { return ;}
    if(empty_node(H)) 
    {
        printf("链表元素为空,无须删除\n");
        return ;
    }
    node_p p=H->next;
    if(p->next==NULL)
    {
        free(p);
        H->next=NULL;
        H->pri=NULL;
        H->len--;
    }
    p->next->pri=H; //p结点的后驱的前驱指向头结点
    H->next=p->next;  //头结点的后驱指向p结点的后驱 
    free(p);
    H->len--;
    return ;
}
//8、尾删
void dele_tail(node_p H)
{
    if(H==NULL) { return ;}
    if(empty_node(H)) 
    {
        printf("链表元素为空,无须删除\n");
        return ;
    }
    node_p p=H;
    while(p->next->next!=NULL)
    {
        p=p->next;
    }
    H->pri=p->next->pri; //头结点的前驱指向p结点
    p->next=H; //p结点的后驱指向头结点
    free(p->next); //释放p结点的后驱结点
    H->len--;
}
//9、按位置删除
void dele_pos(node_p H,int pos)
{
    if(H==NULL) { return ;}
    if(empty_node(H)) 
    {
        printf("链表元素为空,无须删除\n");
        return ;
    }
    if(pos<1 || pos>H->len)
    {
        printf("删除元素位置不合理\n");
        return ;
    }
    int i;
    node_p p;
    //循环找出需要删除元素的位置
    for(i=0,p=H;i<pos-1;i++,p=p->next);
    if(p->next==NULL)
    {
        p->pri->next=H;
        H->pri=p->pri;
        free(p);
        H->len--;
    }
    p->next->pri=p->pri; //p结点后驱的前驱指向p结点的前驱
    p->pri->next=p->next; //p结点前驱的后驱指向p结点的后驱
    free(p);
    H->len--;
}
//10、按位置查找
int seek_pos(node_p H,int pos)
{
    if(H==NULL) { return -1;}
    if(empty_node(H)) 
    {
        printf("链表元素为空,无法找到目标值\n");
        return -2;
    }
    if(pos<1 || pos>H->len)
    {
        printf("删除元素位置不合理\n");
        return -3;
    }
    int i;
    node_p p;
    //循环找出目标位置的元素
    for(i=0,p=H;i<pos-1;i++,p=p->next);
    int num=p->data; //获取目标位置的元素
    return num;
}
//输出链表
void show_node(node_p H)
{
    if(H==NULL) { return ;}
    if(empty_node(H)) 
    {
        printf("链表元素为空,无须打印\n");
        return ;
    }
    node_p p=H->next;
    do
    {
        printf("%d-> ",p->data);
        p=p->next;
    }while(p->next!=H);
    return;
}

loop.h

#ifndef __LOOP_H__
#define __LOOP_H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct node
{
    union
    {
        int data;
        int len;
    };
    struct node *pri;
    struct node *next;
}node,* node_p;
node_p create_link();
node_p create_node(int value);
int empty_node(node_p H);
void insert_head(node_p H,int value);
void insert_tail(node_p H,int value);
void insert_pos(node_p H,int pos,int value);
void dele_head(node_p H);
void dele_tail(node_p H);
void dele_pos(node_p H,int pos);
int seek_pos(node_p H,int pos);
void show_node(node_p H);
#endif

二、链表和顺序表的优缺点:

顺序表可通过下标访问,访问速度快,静态分配内存利用高,插入和删除需要移动后续数据效率低。

链表通过指针访问,访问速度慢,动态分配内存利用不高,插入和删除可通过指针完成效率高。

三、牛客刷题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值