双向循环链表

3 篇文章 0 订阅
2 篇文章 0 订阅

循环与不循环区别

单向链表:只有一个指向下一个节点的指针。

优点:单向链表增加删除节点简单。遍历时候不会死循环;

缺点:只能从头到尾遍历。只能找到后继,无法找到前驱,也就是只能前进。

适用于节点的增加删除。

双向链表:有两个指针,一个指向前一个节点,一个后一个节点。

优点:可以找到前驱和后继,可进可退;

缺点:增加删除节点复杂,需要多分配一个指针存储空间。

适用于需要双向查找节点值的情况

下面讲解双向循环链表的一般写法:

#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
#define ture 1
#define false 0
typedef unsigned char bool;

typedef struct list{
    struct list *prev;
    int data;
    struct list *next;
}List;

List *CreatList(void)
{
    List *head = (List *)malloc(sizeof(List));
    if(head == NULL)
    {
        return (List *)ERROR;
    }
    head->prev = head;
    head->next = head;
    return head;
}

List *CreatNodeForList(int n)
{
    List *node = (List *)malloc(sizeof(List));
    if(node == NULL)
    {
        return (List *)ERROR;
    }
    node->next = NULL;
    node->prev = NULL;
    node->data = n;
    return node;
}

/**通过表头插入***********/
static bool InsetNodeToListByHead(List *head,int n)
{
    if(head == NULL)
    {
        return ERROR;
    }
    List *node = CreatNodeForList(n);
    node->prev = head;//第一步:连线,新结点的上一个是头
    node->next = head->next;//第二步:连线,新结点的下一个是头的下一个
    head->prev->next = node;//第三步:头的上一个的下一个是新结点
    head->next = node;//第四步:头的下一个是新结点
    return OK;
}

/**通过表尾部插入*********/
static bool InsetNodeToListByTail(List *head,int n)
{
    if(head == NULL)
    {
        return ERROR;
    }
    List *node = CreatNodeForList(n);
    List *last = head;
    while(last->next != head)
    {
        last = last->next;
    }
    head->prev = node;
    node->next = head;
    last->next = node;
    node->prev = last;
    return OK;
}

/**指定位置删除结点********/
static bool SpecifyLocationToDelete(List *head,int dele)
{
    List *dlnode = head->next;//指定结点指针
    List *dlnodep = head;//指定结点前一个结点的指针
    while(dlnode->data != dele)
    {
        dlnodep = dlnode;
        dlnode = dlnodep->next;
        if(dlnode->next == head)
        {
            printf("\r\n该结点不存在,无法删除!\r\n");
            return ERROR;
        }
    }
    dlnodep->next = dlnode->next;
    dlnode->next->prev = dlnodep;
    free(dlnode);
    dlnode = NULL;
    printf("\r\n删除成功\r\n");
    return OK;
}

/**搜索指定元素*********/
static bool SearchSpecifyElement(List *head,int seek)
{
    List *sknode = head->next;//指定结点指针
    List *sknodep = head;//指定结点前一个结点的指针
    int record = 1;
    while(sknode->data != seek)
    {
        sknodep = sknode;
        sknode = sknodep->next;
        record++;
        if(sknode == head)
        {
            printf("\r\n不存在该元素\r\n");
            return ERROR;
        }
    }
    printf("\r\n存在该元素,是第%d个结点\r\n",record);
    return OK;
}

/**修改指定的元素********/
static bool ModifySpecifyElement(List *head,int mod,int elmt)
{
    List *monode = head->next;//指定结点指针
    List *monodep = head;//指定结点前一个结点的指针
    int record = 1;
    while(monode->data != mod)
    {
        monodep = monode;
        monode = monodep->next;
        record++;
        if(monode == head)
        {
            printf("\r\n不存在该元素,无法修改\r\n");
            return ERROR;
        }
    }
    monode->data = elmt;
    printf("\r\n存在该元素,是第%d个结点,可以修改\r\n",record);
    return OK;
}

/**打印链表中的元素******/
static bool PrintfList(List *head)
{
    List *print = head->next;
    while(print != head)
    {
        printf("->%d",print->data);
        print = print->next;
    }
    printf("\n");
    return OK;
}

static int AddNumberToLink(void)
{
    int number;
    fprintf(stdout,"请输入数据存入链表中,输入0则结束\r\n");
    scanf("%d",&number);
    return number;
}


/**菜单***************/
static void Menu(void)
{
	printf("+===========================================+\n");
	printf("|    1.表头插入元素     2.表尾插入元素          |\n");
	printf("+===========================================+\n");
	printf("|    3.删除指定元素     4.修改指定元素          |\n");
	printf("+===========================================+\n");
	printf("|    5.搜索指定元素     6.打印双向链表          |\n");
	printf("+===========================================+\n");
	printf("|    0.退出                                  |\n");
	printf("+===========================================+\n");
}

int main(int argc,char **argv)
{
    List *head = CreatList();
    int rel = AddNumberToLink();
    while(rel)
    {
        InsetNodeToListByHead(head,rel);
        rel = AddNumberToLink();
    }
    Menu();
    int choose = 1;
    while(choose)
    {
        printf("\r\n请输入你的选择\r\n");
        scanf("%d",&choose);
        int tmp,temp;
        switch(choose){
            case 1:{
                printf("\r\n请输入要插入的元素\r\n");
                scanf("%d",&tmp);
                InsetNodeToListByHead(head,tmp);
            }break;
            case 2:{
                printf("\r\n请输入要插入的元素\r\n");
                scanf("%d",&tmp);
                InsetNodeToListByTail(head,tmp);
            }break;
            case 3:{
                printf("\r\n请输入要删除的元素\r\n");
                scanf("%d",&tmp);
                SpecifyLocationToDelete(head,tmp);
            }break;
            case 4:{
                printf("\r\n请输入要修改的元素\r\n");
                scanf("%d",&tmp);
                printf("\r\n请输入新的元素\r\n");
                scanf("%d",&temp);
                ModifySpecifyElement(head,tmp,temp);
            }break;
            case 5:{
                printf("\r\n请输入您要搜索的元素\r\n");
                scanf("%d",&tmp);
                SearchSpecifyElement(head,tmp);
            }break;
            case 6:{
                PrintfList(head);
            }break;
            default:
                break;
            printf("\n");
            Menu();
        }
        printf("\n");
        Menu();
    }
    return OK;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值