带头循环单链表的基本操作

记录一下写过的代码,

//list.h

#include <stdio.h>


//封装一个带头循环单链表
typedef struct Element{
    int data;
    //other field
} Element;

typedef struct Node{
    Element elem;
    struct Node * link;
}Node;

typedef Node * NodePointer;

void initList(NodePointer * plist);
int insertList(NodePointer * plist, const Element * e); //尾部插入
int deleteList(NodePointer * plist, const Element * e); //根据e删除一个节点
NodePointer invertList(NodePointer list);//反转一个链表
void destoryList(NodePointer * plist);
void showList(const NodePointer * plist);


//list.c


#include "list.h"
#include <stdlib.h>
#include <memory.h>

void initList(NodePointer * plist)
{
    NodePointer pnode;
    
    if(plist == NULL)
    {
        printf("initList error.\n");
        exit(1);
    }
    pnode = (NodePointer)malloc(sizeof(Node));
    if(!pnode)
    {
        printf("initList malloc error.\n");
        exit(1);
    }
    pnode->link = pnode;
    *plist = pnode;
    return ;
}


int insertList(NodePointer * plist, const Element * e) //尾部插入
{
    NodePointer pnode, rear;
    
    pnode = (NodePointer)malloc(sizeof(Node));
    if(!pnode)
    {
        printf("insertList malloc error.\n");
        return 0;
    }
    rear = (*plist);
    while(rear->link != *plist)
        rear = rear->link;
    pnode->elem = *e;
    pnode->link = *plist;
    rear->link = pnode;
    
    return 1;
}

int deleteList(NodePointer * plist, const Element * e) //根据e删除一个节点
{
    NodePointer pnode, prev;
    
    prev = (*plist);
    pnode = (*plist)->link;
    while(pnode != *plist)
    {
        if(memcmp(&(pnode->elem), e, sizeof(Element)) == 0)
        {
            prev->link = pnode->link;
            free(pnode);
            return 1;
        }
        prev = pnode;
        pnode = pnode->link;
    }
    return 0;
}

NodePointer invertList(NodePointer  list)//反转一个链表
{
    NodePointer current, prev;
    NodePointer temp;
    
    prev = list;
    current = prev->link;
    while(current != list)
    {
        temp = current->link;
        current->link = prev;
        prev = current;
        current = temp;
    }
    current->link = prev;
    
    return current;
}


void destoryList(NodePointer * plist)
{
    NodePointer pnode, temp;
    
    pnode = (*plist)->link;
    while(pnode != *plist)
    {
        temp = pnode;
        pnode = pnode->link;
        free(temp);
    }
    free(pnode);
}

void showList(const NodePointer * plist)
{
    NodePointer pnode;
    int count = 0;
    
    pnode = (*plist)->link;
    while(pnode != *plist)
    {
        printf("%d\t", (pnode->elem).data);
        pnode = pnode->link;
        if(count++ % 5 == 4)
            printf("\n");
    }
}


从上面的插入节点函数可以看出其效率非常低, 因为每次插入节点都需要遍历一遍整个链表,查找到尾节点。

解决办法是,不用头节点,使用链表的尾节点指针作为插入函数的参数,这样可以方便的插入到表头表尾。

如 rear,表示尾节点, node 是需要插入的节点

头插: node->link = rear->link; rear->link = node;

尾插:node->link = rear->link; rear->link = node; rear = node;


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值