单向循环链表的简单实现

来源:互联网 发布:windows10 配置mysql 编辑:程序博客网 时间:2024/05/17 05:57
单向循环链表:
      在单向链表中,头指针是相当重要的,因为单向链表的操作都需要头指针,所以如果头指针丢失或者破坏,那么整个链表都会遗失,并且浪费链表内存空间。

单向循环链表的构成:
      如果把单链表的最后一个节点的指针指向链表头部,而不是指向NULL,那么就构成了一个单向循环链表。
单向链表结构图示:(以下示意图均摘自来源: http://blog.csdn.net/fisherwan/ar


单向循环链表的初始化:


当单向循环链表中只有一个节点时,那么这个节点的next指针指向的就是这个节点本身。

单向循环链表的创建:


        单向循环链表的创建和单向链表很相似,不同的地方是新插入节点的next指向的不再是NULL,而是指向第一个节点。
代码如下:
遍历到链表的最后一个节点ptemp;
ptemp->next = pnew;
pnew->next = head;

单向循环链表的插入:


单向循环链表的插入与单向链表有所不同,因为单向循环链表首尾相连,所以没有从尾部插入的问题。
(1)从链表头部插入
将新插入的节点变为链表头部,next指向原来的第一个节点,在遍历整个链表找到链表末尾(即它的next指向的是head的那个节点),将这个节点的next指向新插入的节点,最后再将链表头指针指向新节点。
代码如下:
pnew->next = head->next;
ptemp = head;
while(ptemp->next != head)     //注意此时的遍历条件是ptemp->next != head
        ptemp = ptemp->next;    //退出while循环后ptemp指向链表尾部
ptemp->next = pnew;
head = pnew;
(2)从链表中间插入
此时插入的过程和单向链表的一样,找到要插入位置前驱节点ptemp,将新插入节点的next指向ptemp的next,再将ptemp的next指向新插入的节点pnew。
代码如下:
pnew->next = ptemp->next;
ptemp->next  = pnew;
以上的顺序不能变

单向循环链表的删除:


删除操作与插入操作类似,也分为两种情况:
(1)在链表头部删除
将链表头指针指向第二个节点,再将最后一个节点的指针指向新插入的节点,最后释放掉原来第一个节点的内存空间
代码如下:
ptemp = head;
first = head;
while(ptemp->next != head)
    ptemp = ptemp->next;  //退出while循环后ptemp指向链表尾部
head= head->next;//头指针指向第二个节点
ptemp->next = headt;//指向第二个节点
free(first);//释放掉原来的第一个节点
(2)在链表中间删除
找到要删除的链表的前驱节点ptr,将ptr的next指向pdelete的next,再释放掉pdelete的内存空间。
代码如下:
ptr = head;
while(ptr->next != del)
    ptr = ptr->next;//退出循环后此时ptr为pdelete的前驱
pdelete = ptr->next;
ptr-next = pdelete->next;

单向循环链表的C语言实现:(codeblocks完美运行)
#include <stdlib.h>#include <stdio.h>typedef struct circle_list{int date;struct circle_list *next;}list;//节点创建函数list *creat_node(){     //创建头节点  list *newnode = (list *)malloc(sizeof(struct circle_list));        if(newnode == NULL){printf("创建头结点失败!\n");}            else{newnode->next=NULL;return newnode;}}//插入数据到链表中int insert_list(list *head){    //创建节点    int val;    printf("请输入要插入的元素:");    scanf("%d",&val);list *newnode =  creat_node();newnode->date = val;//判断头节点是否为NULL    if(head != NULL){        //遍历头节点,中间变量P         list *p  = head;//遍历头节点到,最后一个数据while(p->next != head ){//错误,这样会改变头节的位置,必须使用中间变量进行变量    // head = head->next;p = p->next;}//把最后一个节点赋新的节点过去p->next = newnode;newnode->next = head;return 1;}else{ printf("head is NULL\n"); return 0;}}//遍历链表中的数据int display(list *head){       if(head != NULL){        //遍历头节点,中间变量P         list *p  = head;//遍历头节点到,最后一个数据while(p->next != head ){//错误,这样会改变头节的位置,必须使用中间变量进行变量    // head = head->next;                printf("%d   ",p->next->date);p = p->next;}//把最后一个节点赋新的节点过去return 1;}else{            printf("头结点为空!\n");            return 0;}}int delete_list(list *head){    if(head == NULL)    {        printf("链表为空!\n");        return 0;    }    list *temp = head;    list *ptr = head->next;    int del;    printf("请输入你要删除的元素:");    scanf("%d",&del);    while(ptr != head)    {        if(ptr->date == del)        {            if(ptr->next == head)//循环结束的条件换成ptr->next == head            {                temp->next = head;                free(ptr);                return 1;            }            temp->next = ptr->next;            free(ptr);            //printf("元素删除成功!\n");            return 1;        }        temp = temp->next;        ptr = ptr->next;    }    printf("没有找到要删除的元素%d\n",del);    return 0;}int update_list(list *head){    if(head == NULL)    {        printf("链表为空!\n");        return 0;    }    list *temp = head;    int olddate,newdate;    printf("请输入要修改的元素:");    scanf("%d",&olddate);    printf("修改为:");    scanf("%d",&newdate);    while(temp->next != head)    {        if(temp->next->date == olddate)        {            temp->next->date = newdate;            return 1;        }        temp = temp->next;    }    printf("没有找到要修改的元素!\n");    return 0;}int seek_list(list*head){    if(head == NULL)    {        printf("链表为空!\n");        return 0;    }    int val,i=0;    printf("请输入要查找的元素:");    scanf("%d",&val);    list *p = head;    while(p->next != head)    {        i++;        if(p->next->date == val)        {            printf("找到元素%d,位置在%d\n",val,i);        }        p = p->next;    }    printf("没有找到该元素!\n");    return 0;}void menu(){    system("cls");//清屏    printf("\t\t|===============================================|\t\t\n");    printf("\t\t|==================单向循环操作=================|\t\t\n");    printf("\t\t|===================1.插入元素==================|\t\t\n");    printf("\t\t|===================2.打印链表==================|\t\t\n");    printf("\t\t|===================3.删除元素==================|\t\t\n");    printf("\t\t|===================4.修改链表==================|\t\t\n");    printf("\t\t|===================5.查找元素==================|\t\t\n");    printf("\t\t|==请输入对应的数字执行对应的功能!(输入0退出)==|\t\t\n");    printf("\t\t|======   作者:RXX    时间:2017/07/06   ======|\t\t\n");    printf("\t\t|===============================================|\t\t\n");}int main(){    //创建头节点    list *head = creat_node();    //让头字节自我循环    head->next = head;    int num;    menu();    scanf("%d",&num);    //插入节点    while(num)    {        switch(num)        {            case 1:            {                printf("插入元素操作:\n");                if(insert_list(head))                    printf("插入节点成功!\n");                else                    printf("插入节点失败!\n");                break;            }            case 2:            {                printf("打印链表操作:\n");                display(head);                break;            }            case 3:            {               if(delete_list(head))                    printf("删除节点成功!\n");                break;            }            case 4:            {               if(update_list(head))                    printf("修改元素成功!\n");                break;            }            case 5:            {               if(seek_list(head))                    printf("查找元素成功!\n");                break;            }        }        getch();        menu();        scanf("%d",&num);  //清空缓存区//while(getchar()!='\n');    }    printf("\t\t|================感谢使用!再见!===============|\t\t\n");    return 0;}

运行界面:




原创粉丝点击