数据结构算法-单向循环链表

349 阅读2分钟

单向循环链表

如图所示当最后一个节点当next 指向首元节点时,单向链表就变成了单向循环链表

首先我们定义一个数据结构用于存储数据

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

单向链表的创建 (根据idx 选择插入位置),创建单向循环链值得注意当是

  • 1.第一次创建
  • 2.已经创建,新增数据

代码如下:

// 单向循环链表 第idx  位置插入数据
Status CreateLinkList (LinkList *L ,int idx , ElemType e){
    
    if ( *L == NULL) {
        (*L) = (LinkList)malloc(sizeof(Node));
        if(!*L) return ERROR;
        (*L)->data = e;
        (*L)->next = *L;
      
    }else{
        LinkList p,temp;
        p = *L;
        int j ;
//      找到最后一个节点
        for (j = 1; j < idx && p->next != *L; j++ ,p = p->next);
        if (j< idx) {
                printf("idx越界超出插入范围!\n");
            return  ERROR;
               
           }
        //        p 为当前要插入的节点 j 为当前要插入的节点位置
        temp = (LinkList)malloc(sizeof(Node));
        if (!temp) return ERROR;
        temp->data = e;
        temp->next = p->next;
        p->next = temp;
    }
    return SUCCESS;
}

输出结果为 1-100, 当然 CreateLinkList 支持以任何节点插入数据

单向循环链表单删除

删除节点单时候, (根据idx 选择删除位置),也有一些值得注意当是

  • 1.是否为首元节点
  • 2.删除节点的时候要先接收所要删除节点的next,单链会丢失

代码如下:

// 单向循环链表 第idx  位置删除节点
LinkList deleteLinkList (LinkList *L ,int idx ){
    
    LinkList p ,temp;
    p = *L
    int j ;
    if (p == NULL) return NULL;
    
    if(idx == 1){
//        如果删除到只剩下首元结点了,则直接将*L置空;
        if((*L)->next == (*L)){
                  (*L) = NULL;
                  return SUCCESS;
            }
//        获取下最后一个
        while (p->next != *L) {
            p = p->next;
        }
        temp = *L;
        *L = (*L)->next;
        p->next = *L;
    
    }else{

//    容错处理
        for (j=1; j<idx && p->next != *L; j++,p= p->next) {
            temp = p->next;
            p->next = temp->next;
            free(temp);
        }
  
    }
    
    return p->next;
}

注意以上代码返回值为什么是个LinkList?,当然返回值是我们自己用于定义的,为什么返回LinkList 主要是下面我们将会用到,(解约瑟夫)

  • 如题:有n个人,编号为1~n,从第一个人开始报数,从1开始报,报到m的人会死掉,然后从第m+1个人开始,重复以上过程。在死了n-1个人后,问最后一个人的编号是?

//约瑟夫解法
ElemType ysfList(LinkList *L ,int idx ){
 
    LinkList p , temp;
    p = *L;
    int j ,sum;
    
    if (p->next == *L) return (*L)->data;
//    容错处理 先求下总长度
    for (sum = 1; p->next != *L;  sum ++, p = p->next) ;
    if (sum > 1){
        j = (sum > 1)?(idx %  sum):idx;
//        删除对应位置的节点,并返回next
        temp = deleteLinkList(L ,j-1);
//        printf("删除后下一次开始数的\n");
//        ListTraverse(temp);
        ysfList(&temp  , idx);
    }
     return (*L)->data;
}

之后我们就可以随机输入看看效果了