数据结构学习——循环链表的使用

一、循环链表的介绍

        循环链表是一种特殊类型的链表,其中链表中的最后一个节点指向链表中的第一个节点,形成循环的结构。与普通链表相比,循环链表可以在链表中的任何位置进行遍历,并且可以方便地实现循环操作。在循环链表中,每个节点通常包含一个数据元素和一个指向下一个节点的指针。链表中的最后一个节点的指针指向第一个节点,形成闭环。

二、循环链表的创建以及初始化

        进行链表初始化时,以用户键盘输入“0” 作为结束标志,通过链表初始化函数,可直接规定了链表长度。

typedef struct Node{
    int data;
    struct Node* next;
}Node;

//结构体定义

void Node_init(Node **head){
    int item;
    Node* target;
    printf("输入节点的值,输入0完成初始化\n");
    while(1){
        scanf("%d",&item); //item为从键盘输入插入节点的值
        if( item==0 )return;
        if((*head)==NULL){ //当循环链表头节点为空的时候
            *head = (Node *)malloc(sizeof(struct Node));
            if(!(*head))exit(0);
            (*head)->data = item;
            (*head)->next = *head;
        }
        else{
            //找到最后一个节点进行尾插
            for(target = *head; target->next != *head; target = target->next);
            Node* temp = (Node *)malloc(sizeof(struct Node));
            if(!temp)exit(0);
            temp->data = item;
            temp->next = *head;
            target->next = temp;
        }
    }
}

三、菜单栏样式设置

        本程序做了一个菜单选择页面,提供给用户从键盘输入选择不同的操作。效果如图:

 代码部分:

void Style_set(){
    int j,height = 5,width = 60;
    for(j = 0; j < width; j++)printf("*");
    printf("\n*");
    for(j = 0; j < (width - 20)/2 ; j++)printf(" ");
    printf("请输入要进行的操作选项:");
    for(j = 0; j < (width - 30)/2 ; j++)printf(" ");
    printf("*\n");

    printf("*");
    for(j = 0; j < (width - 20)/2; j++)printf(" ");
    printf("(1).初始化链表");
    for(j = 0; j < (width - 12)/2; j++)printf(" ");
    printf("*\n");

    printf("*");
    for(j = 0; j < (width - 20)/2; j++)printf(" ");
    printf("(2).插入新节点");
    for(j = 0; j < (width - 12)/2; j++)printf(" ");
    printf("*\n");
    
    printf("*");
    for(j = 0; j < (width - 20)/2; j++)printf(" ");
    printf("(3).删除指定结点");
    for(j = 0; j < (width - 16)/2; j++)printf(" ");
    printf("*\n");

    printf("*");
    for(j = 0; j < (width - 20)/2; j++)printf(" ");
    printf("(4).查找指定结点");
    for(j = 0; j < (width - 16)/2; j++)printf(" ");
    printf("*\n");

    printf("*");
    for(j = 0; j < (width - 20)/2; j++)printf(" ");
    printf("(5).遍历链表");
    for(j = 0; j < (width - 8)/2; j++)printf(" ");
    printf("*\n");

    for(j = 0; j < width; j++)printf("*");
    printf("\n");
}

四、链表插入节点

        这里写的函数可以指定链表位置进行插入。

void insert_node( Node** head,int i){
    int j = 1;
    Node* target = *head;
    int item;
    printf("请输入插入结点的值\n");
    scanf("%d",&item);
    if(!item) exit(0);
    if(i == 1){
        struct Node* temp = (Node*)malloc(sizeof(struct Node));
        temp->data = item;
        for( ;target->next != *head; target = target->next);
        temp->next = *head;
        target->next = temp;
        *head = temp;
    }
    else{
        if(!item)exit(0);
        target = *head;
        for( ; j < (i-1); j++)
        target = target->next;
        Node* temp = (Node*)malloc(sizeof(struct Node));
        temp->data = item;
        Node* p = target->next;
        target->next = temp;
        temp->next = p;
    }
}

五、删除一个节点

        与指定位置插入节点类似,在删除节点时同样也能够指定位置,通过找到指定位置的前驱节点,从前驱节点断开并将其next指向删除节点的下一个节点,最后在释放掉删除节点的内存。

void delete_node(Node **head,int i){
    Node* target;
    int j = 1;
    if( i==1 ){//删除第一个结点
    for(target = *head ; target != *head; target = target->next);
    Node* temp = *head;
    *head = (*head)->next;
    target->next = *head;
    free(temp);
    }
    else{
        target = *head;
        for( ; j < (i-1); j++)
        target = target->next;//寻找删除位置结点的前驱结点
        Node* temp = target->next;
        target->next = temp->next;
        free(temp);
    }
}

六、按值查找对链表搜索

        这里只传递结构体,不对其修改,因此不需要用指针指向结构体,将查找的值从链表的头节点开始逐个比较,当比较到最后一个节点依然没有找到时就提示找不到该元素,若找到则返回该节点所在的位置。

int Search_Node(Node* head, int value){
    Node* target;
    int i = 1;
    for(target = head; target->data != value && target->next != head; ++i)
    target = target->next;
    if(target->next = head) //不存在该元素
    return 0;
    else  
    return i;
}

七、循环链表的遍历

        与单链表的遍历仅多了对尾节点的下一节点是否是头节点的判断。

void PrintOut_Link(Node *head){
    Node* temp = head;
    printf("***********链表中的元素为************\n");
    do
    {
        printf("%4d ",temp->data);
    } while ((temp = temp->next) != head);
    printf("\n");       
}

八、主函数以及全部代码

void main(){
    char opp;
    int pos;
    Node* head = NULL;
    Style_set();
    while( opp != '0'){
        scanf("%c",&opp);
        switch(opp){
            case '1' :
                Node_init(&head);printf("\n");
                PrintOut_Link(head);
                Style_set();
                break;
                break;
            case '2' :
                printf("请输入插入结点的位置\n");
                scanf("%d",&pos);
                insert_node(&head,pos);
                printf("在%d处插入值后:  \n",pos);
                PrintOut_Link(head);
                printf("\n");
                Style_set();
                break;//单个break 
            case '3' :
                printf("请输入要删除结点的位置\n");
                scanf("%d",&pos);
                delete_node(&head,pos);
                printf("在%d处值删除后:  \n",pos);
                PrintOut_Link(head);
                printf("\n");
                Style_set();
                break;
            case '4' :
                printf("请输入要查找结点的值\n");
                scanf("%d",&pos);
                pos = Search_Node(head,pos);
                if(pos == 0)printf("查无此值\n");
                else printf("所查找值的位置是:  %d \n",pos);
                PrintOut_Link(head);
                printf("\n");
                Style_set();
                break;
            case '5' :
                PrintOut_Link(head);
                printf("\n");
                Style_set();
                break;
            case '0' :
                exit(0);
        }   
    }
}

全部代码:

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>

typedef struct Node{
    int data;
    struct Node* next;
}Node;

void insert_node(Node **head,int i);
void Style_set();
void Node_init(Node **head);
void delete_node(Node **head,int i);
int Search_Node(Node* head, int value);
void PrintOut_Link(Node *head);

void main(){
    char opp;
    int pos;
    Node* head = NULL;
    Style_set();
    while( opp != '0'){
        scanf("%c",&opp);
        switch(opp){
            case '1' :
                Node_init(&head);printf("\n");
                PrintOut_Link(head);
                Style_set();
                break;
                break;
            case '2' :
                printf("请输入插入结点的位置\n");
                scanf("%d",&pos);
                insert_node(&head,pos);
                printf("在%d处插入值后:  \n",pos);
                PrintOut_Link(head);
                printf("\n");
                Style_set();
                break;//单个break 
            case '3' :
                printf("请输入要删除结点的位置\n");
                scanf("%d",&pos);
                delete_node(&head,pos);
                printf("在%d处值删除后:  \n",pos);
                PrintOut_Link(head);
                printf("\n");
                Style_set();
                break;
            case '4' :
                printf("请输入要查找结点的值\n");
                scanf("%d",&pos);
                pos = Search_Node(head,pos);
                if(pos == 0)printf("查无此值\n");
                else printf("所查找值的位置是:  %d \n",pos);
                PrintOut_Link(head);
                printf("\n");
                Style_set();
                break;
            case '5' :
                PrintOut_Link(head);
                printf("\n");
                Style_set();
                break;
            case '0' :
                exit(0);
        }   
    }
}

void Node_init(Node **head){
    int item;
    Node* target;
    printf("输入节点的值,输入0完成初始化\n");
    while(1){
        scanf("%d",&item);
        fflush(stdout);
        if( item==0 )return;
        if((*head)==NULL){
            *head = (Node *)malloc(sizeof(struct Node));
            if(!(*head))exit(0);
            (*head)->data = item;
            (*head)->next = *head;
        }
        else{
            for(target = *head; target->next != *head; target = target->next);
            Node* temp = (Node *)malloc(sizeof(struct Node));
            if(!temp)exit(0);
            temp->data = item;
            temp->next = *head;
            target->next = temp;
        }
    }
}

void Style_set(){
    int j,height = 5,width = 60;
    for(j = 0; j < width; j++)printf("*");
    printf("\n*");
    for(j = 0; j < (width - 20)/2 ; j++)printf(" ");
    printf("请输入要进行的操作选项:");
    for(j = 0; j < (width - 30)/2 ; j++)printf(" ");
    printf("*\n");

    printf("*");
    for(j = 0; j < (width - 20)/2; j++)printf(" ");
    printf("(1).初始化链表");
    for(j = 0; j < (width - 12)/2; j++)printf(" ");
    printf("*\n");

    printf("*");
    for(j = 0; j < (width - 20)/2; j++)printf(" ");
    printf("(2).插入新节点");
    for(j = 0; j < (width - 12)/2; j++)printf(" ");
    printf("*\n");
    
    printf("*");
    for(j = 0; j < (width - 20)/2; j++)printf(" ");
    printf("(3).删除指定结点");
    for(j = 0; j < (width - 16)/2; j++)printf(" ");
    printf("*\n");

    printf("*");
    for(j = 0; j < (width - 20)/2; j++)printf(" ");
    printf("(4).查找指定结点");
    for(j = 0; j < (width - 16)/2; j++)printf(" ");
    printf("*\n");

    printf("*");
    for(j = 0; j < (width - 20)/2; j++)printf(" ");
    printf("(5).遍历链表");
    for(j = 0; j < (width - 8)/2; j++)printf(" ");
    printf("*\n");

    for(j = 0; j < width; j++)printf("*");
    printf("\n");
}

void insert_node( Node** head,int i){
    int j = 1;
    Node* target = *head;
    int item;
    printf("请输入插入结点的值\n");
    scanf("%d",&item);
    if(!item) exit(0);
    if(i == 1){
        struct Node* temp = (Node*)malloc(sizeof(struct Node));
        temp->data = item;
        for( ;target->next != *head; target = target->next);
        temp->next = *head;
        target->next = temp;
        *head = temp;
    }
    else{
        if(!item)exit(0);
        target = *head;
        for( ; j < (i-1); j++)
        target = target->next;
        Node* temp = (Node*)malloc(sizeof(struct Node));
        temp->data = item;
        Node* p = target->next;
        target->next = temp;
        temp->next = p;
    }
}

void delete_node(Node **head,int i){
    Node* target;
    int j = 1;
    if( i==1 ){//删除第一个结点
    for(target = *head ; target != *head; target = target->next);
    Node* temp = *head;
    *head = (*head)->next;
    target->next = *head;
    free(temp);
    }
    else{
        target = *head;
        for( ; j < (i-1); j++)
        target = target->next;//寻找删除位置结点的前驱结点
        Node* temp = target->next;
        target->next = temp->next;
        free(temp);
    }
}

int Search_Node(Node* head, int value){
    Node* target;
    int i = 1;
    for(target = head; target->data != value && target->next != head; ++i)
    target = target->next;
    if(target->next = head) //不存在该元素
    return 0;
    else  
    return i;
}

void PrintOut_Link(Node *head){
    Node* temp = head;
    printf("***********链表中的元素为************\n");
    do
    {
        printf("%4d ",temp->data);
    } while ((temp = temp->next) != head);
    printf("\n");       
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值