循环链表的基本操作

循环链表与普通链表最大的区别在于尾结点的指针域指向什么:普通链表的尾结点的指针域指向空(NULL),而循环链表的尾结点的指针域指向头结点,形成一个环!

#include<iostream>
#include<cstdlib>
using namespace std;

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

//函数声明
void show();
void InitList(LinkList &L);
void DestroyList(LinkList &L);
void CreateList(LinkList &L,int length);
void ClearList(LinkList &L);
bool EmptyList(LinkList L);
int LengthList(LinkList L);
int GetElem(LinkList L,int index);
int LocateElem(LinkList L,int e);
bool PriorElem(LinkList L,int cur_e,int &pri_e);
bool NextElem(LinkList L,int cur_e,int &next_e);
bool InsertList(LinkList &L,int index,int value);
bool DeleteList(LinkList &L,int index,int &e);
void Print(LinkList L);

int main(){
    LinkList L;
    int e,index,cur_e,next_e,pri_e,action,length;
    show();
    while(cin>>action){
        switch(action){
            case 1:
                system("cls");
                InitList(L);
                break;
            case 2:
                system("cls");
                cout<<"请输入循环链表中的结点个数:"<<endl;
                cin>>length;
                CreateList(L,length);
                cout<<"创建循环链表成功!"<<endl;
                break;
            case 3:
                system("cls");
                if(EmptyList(L)){
                    cout<<"循环链表为空"<<endl;
                } else {
                    cout<<"循环链表不为空"<<endl;
                }
                break;
            case 4:
                system("cls");
                cout<<"循环链表的长度为:"<<LengthList(L)<<endl;
                break;
            case 5:
                system("cls");
                cout<<"请输入结点的索引"<<endl;
                cin>>index;
                cout<<"第"<<index<<"个结点的值为:"<<GetElem(L,index);
                break;
            case 6:
                system("cls");
                cout<<"请输入结点的值"<<endl;
                cin>>e;
                cout<<e<<"的索引为:"<<LocateElem(L,e);
                break;
            case 7:
                system("cls");
                cout<<"请输入结点的值:"<<endl;
                cin>>e;
                if(PriorElem(L,e,pri_e)){
                    cout<<e<<"的前驱结点的值为:"<<pri_e<<endl<<endl;
                } else {
                    cout<<"循环链表中不包含"<<e<<endl;
                }
                break;
            case 8:
                system("cls");
                cout<<"请输入结点的值:"<<endl;
                cin>>e;
                if(NextElem(L,e,next_e)){
                    cout<<e<<"的后继结点的值为:"<<next_e<<endl<<endl;
                } else {
                    cout<<"循环链表中不包含"<<e<<endl;
                }
                break;
            case 9:
                system("cls");
                cout<<"请输入插入的位置和所插结点的值:"<<endl;
                cin>>index>>e;
                if(InsertList(L,index,e)){
                    cout<<"插入成功"<<endl;
                } else {
                    cout<<"插入失败"<<endl;
                }
                break;
            case 10:
                system("cls");
                ClearList(L);
                cout<<"已清空循环链表"<<endl;
                break;
            case 11:
                system("cls");
                DestroyList(L);
                cout<<"已销毁循环链表"<<endl;
                break;
            case 12:
                system("cls");
                cout<<"请输入将删除的结点的索引"<<endl;
                cin>>index;
                if(DeleteList(L,index,e)){
                    cout<<"第"<<index<<"个元素已经被删除,值为"<<e<<endl<<endl;
                } else{
                    cout<<"删除失败"<<endl;
                }
                break;
            case 13:
                system("cls");
                cout<<"循环链表的各结点为:"<<endl;
                if(!EmptyList(L)){
                    Print(L);
                } else {
                    cout<<"链表为空"<<endl;
                }
                cout<<endl<<endl;
        }
        system("pause");
        system("cls");
        show();
    }
}

void show(){
    cout<<"+------------------------------------------------+"<<endl;
    cout<<"|                                                |"<<endl;
    cout<<"|            1->初始化循环链表                   |"<<endl;
    cout<<"|            2->创建循环链表                     |"<<endl;
    cout<<"|            3->判断链表是否为空                 |"<<endl;
    cout<<"|            4->循环双链表的长度                 |"<<endl;
    cout<<"|            5->获取结点的值                     |"<<endl;
    cout<<"|            6->获取结点的位置                   |"<<endl;
    cout<<"|            7->获取前驱结点                     |"<<endl;
    cout<<"|            8->获取后继结点                     |"<<endl;
    cout<<"|            9->插入结点                         |"<<endl;
    cout<<"|            10->清空循环链表                    |"<<endl;
    cout<<"|            11->销毁循环链表                    |"<<endl;
    cout<<"|            12->删除结点                        |"<<endl;
    cout<<"|            13->打印循环链表                    |"<<endl;
    cout<<"|                                                |"<<endl;
    cout<<"+------------------------------------------------+"<<endl;
}

//初始化循环链表
void InitList(LinkList &L){
    L=new Node;
    if(!L){
        cout<<"初始化失败!"<<endl;
        return;
    }
    L->next=L;
    cout<<"初始化成功!"<<endl;
}

//创建循环链表
void CreateList(LinkList &L,int length){
    LinkList p=L,q;
    for(int i=0;i<length;i++){
        q=new Node;
        cin>>q->data;
        p->next=q;
        p=p->next;
    }
    p->next=L;//注意此时与创建单链表有差异,创建单链表,最后一个结点的指针域为null
    //循环链表的末尾指针域指向头结点
}
//销毁循环链表
void DestroyList(LinkList &L){
    LinkList p,q;
    q=L->next;
    while(q!=L){//没到表尾
        p=q->next;
        delete q;
        q=p;
    }
    delete L;
}

//清空循环链表
void ClearList(LinkList &L){
    LinkList p,q;
    q=L->next;
    while(q!=L){
        p=q->next;
        delete q;
        q=p;
    }
    //前面一部分与销毁表相同,区别在于销毁表会删除头节点,清空表保留头节点,并使头结点的next指向自己
    L->next=L;
    cout<<"已清空循环链表"<<endl;
}

//判断是否为空
bool EmptyList(LinkList L){
    if(L->next==L){
        return true;
    } else {
        return false;
    }
}

//获取长度
int LengthList(LinkList L){
    int i=0;
    LinkList p=L->next;
    while(p!=L){
        i++;
        p=p->next;
    }

    return i;
}

//获取第index个结点的值
int GetElem(LinkList L,int index){
    if(index<0 || index>LengthList(L)){
        cout<<"输入的数值错误"<<endl;
        return 0;
    }
    LinkList p=L->next;
    int j=0;
    while(j<index){
        p=p->next;
        j++;
    }
    return p->data;
}

//获取结点e的位置
int LocateElem(LinkList L,int e){
    LinkList p=L->next;
    int index=1;
    while(p!=L){
        if(e==p->data){
            return index;
        }
        index++;
        p=p->next;
    }
    return 0;
}

//获取当前结点的前一个结点的值
bool PriorElem(LinkList L,int cur_e,int &pri_e){
    //cur_e不为第一个元素
    LinkList p=L->next,q;//p指向第二个元素
    q=p->next;//q指向p的下一个元素
    while(q!=L){
        if(q->data==cur_e){
            pri_e=p->data;
            return true;
        }
        p=q;
        q=q->next;
    }
    return false;
}

//获取当前结点的下一个结点的值
bool NextElem(LinkList L,int cur_e,int &next_e){
    //cur_e不为最后一个元素
    LinkList p=L->next;
    while(p!=L){
        if(p->data==cur_e){
            next_e=p->next->data;
            return true;
        }
        p=p->next;
    }
    return false;
}

//在第index个位置插入结点
bool InsertList(LinkList &L,int index,int value){
    if(index<0 || index>LengthList(L)){
        return false;
    }
    LinkList p=L,q;
    int j=1;
    while(p->next!=L && j<index){
        p=p->next;
        j++;
    }
    q=new Node;
    q->data=value;
    q->next=p->next;
    p->next=q;
    return true;
}

//删除第index个结点
bool DeleteList(LinkList &L,int index,int &e){
    if(index<0 || index>LengthList(L)){
        return false;
    }
    LinkList p=L,q;
    int j=1;
    while(j<index && p->next!=L){
        p=p->next;
        j++;
    }
    q=p->next;
    e=q->data;
    p->next=q->next;
    delete q;
    return true;
}

void Print(LinkList L){
    LinkList p=L->next;
    while(p!=L){
        cout<<p->data<<‘ ‘;
        p=p->next;
    }
}

  

时间: 2024-08-24 23:51:26

循环链表的基本操作的相关文章

Java实现双向循环链表的基本操作

1 package Eric.ADT; 2 3 /** 4 * <p> 5 * Title:doubleLinkedList 6 * </p> 7 * <p> 8 * Description:用java实现双向循环链表的基本操作 9 * </p> 10 * <p> 11 * Location:Frostburg 12 * </p> 13 * 14 * @author: Eric.Chen 15 * @date:2017年9月23日下午

数据结构_线性表_链式存储_双向循环链表的基本操作

//双向链表,将头结点和尾结点链接起来,就构成了双向循环链表 //双向循环链表是将头结点的前驱指针指向了尾结点,同时将尾结点的后劲指针指向了头结点. //空表,头结点的前驱和后继指针均指向了自己,这也是判断双向循环链表是否为空的条件, //双向循环链表具有对称性 //缺点,是要付出空间代价的 双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱.所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点.一般我们都构造双向循环链表. 代

数据结构_线性表_链式存储_单向循环链表的基本操作

1.概述: 对于一个循环链表来说,其首节点和末节点被连接在一起.这种方式在单向和双向链表中皆可实现.要转换一个循环链表,可以选择开始于任意一个节点然后沿着列表的任一方向直到返回开始的节点.再来看另一种方法,循环链表可以被视为"无头无尾".这种列表很利于节约数据存储缓存, 假定你在一个列表中有一个对象并且希望所有其他对象迭代在一个非特殊的排列下. 指向整个列表的指针可以被称作访问指针. 用单向链表构建的循环链表 循环链表中第一个节点之前就是最后一个节点,反之亦然.循环链表的无边界使得在这

链表(五)——单向循环链表

1.单向循环链表 区分单向链表和单向循环链表:单向循环链表的尾指针指向头结点. 2.单向循环链表的基本操作 #include <stdio.h> #include <malloc.h> #define NULL 0 typedef struct node { int data; struct node *next; }ElemSN; ElemSN * creat_link(int ms); //创建一个单向循环链表 void print_link(ElemSN *head); //

循环链表之双循环链表

接着上一篇博文http://12172969.blog.51cto.com/12162969/1918256,把循环链表里的双循环链表的基本操纵按照我个人的理解进行总结一下. 依然沿袭过去的风格,进入双循环链表之前,先提另一种结构,双向链表,先有了双向链表再有了双循环链表.这两种结构和单链表一样都有带头结点和不带头结点之分.我们先来看一下这几种结构的结构图: 双链表 双循环链表 既然单向链表有普通的链表也就是不循环的链表.那么双向链表也一样,也有普通的双向链表和双向循环链表:也有带头结点,不带头

(java实现)双向循环链表

什么是双向循环链表 在了解双向循环链表之前,如果对链表还没有一个清晰的概念,建议你看看单链表和单向循环链表,这有利于你更好的理解下面的内容.(废话有点多[逃] 相比单链表,双向循环链表是一个更加复杂的结构.因为双向循环链表的节点不仅包含指向下一个节点的指针(next),还包含指向前一个节点的指针(prev). 在双向循环链表中,可见的不只有头指针head,还有尾节点end.这是和单链表的区别. 双向循环链表的头指针head的前一个节点指向end,尾节点end的后一个节点指向head. 基本操作

数据结构概述&lt;2&gt;链表的基本概念

一 链表的定义 讨论链表之前,先说线性表. 线性表是一种最常用且最简单的数据结构.一个线性表是n个数据元素的有限集合.对于一个非空的线性表,一般存在几个特征:(1)存在唯一的一个被称作"第一个"的数据元素:(2)存在唯一的一个被称为"最后一个"的数据元素:(3)除第一个之外,线性表中的每个数据元素均只有一个前驱:(4)除最后一个之外,集合中每个数据元素均只有一个后继. 最常见的线性表就是数组了.对于数组而言,每个元素的存储空间相邻,其逻辑关系上相邻的两个元素,在物理

Java数据结构和算法之链表

三.链表 链结点 在链表中,每个数据项都被包含在'点"中,一个点是某个类的对象,这个类可认叫做LINK.因为一个链表中有许多类似的链结点,所以有必要用一个不同于链表的类来表达链结点.每个LINK对象中都包含一个对下一个点引用的字段(通常叫做next)但是本身的对象中有一个字段指向对第一个链结点的引用. 单链表 用一组地址任意的存储单元存放线性表中的数据元素. 以元素(数据元素的映象)  + 指针(指示后继元素存储位置)  = 结点(表示数据元素 或 数据元素的映象) 以"结点的序列&q

双向链表模拟

我们熟悉了java单向链表的模拟,现在我就必须开始双向链表的模拟的. 1.基础结构对象DuLNode public class DuLNode { private Object data;// 存放结点值 private DuLNode prior; // 前驱结点的引用 private DuLNode next; // 后继结点的引用 public DuLNode() {// 无参数时的构造函数 this(null); } public DuLNode(Object data) {// 构造值