精华内容
下载资源
问答
  • //不带头节点的单链循环链表,尾节点的next指向第一个节点 typedef struct NNode { int data;//数据 struct NNode *next;//下一个节点的地址 }NNode,*PNList; //初始化函数,将头指针置NULL,会出现二级指针 void ...

    创建头文件nlist.h

    #pragma once
    //不带头节点的链表,主要应用在循环链表中,其缺点,操作复杂(会出现二级指针),
    //优点:灵活(头指针指向哪个节点哪个节点就是第一个节点)
    //不带头节点的单链循环链表,尾节点的next指向第一个节点
    
    typedef struct NNode
    {
     int data;//数据
     struct NNode *next;//下一个节点的地址
    }NNode,*PNList;
    
    //初始化函数,将头指针置NULL,会出现二级指针
    void InitList(PNList *pplist);
    
    //头插,需要修改头指针,会出现二级指针
    bool Insert_head(PNList *pplist,int val);
    
    //尾插,有可能需要修改头指针,会出现二级指针
    bool Insert_tail(PNList *pplist,int val);
    
    //在plist中查找关键字key,找到返回下标,失败返回NULL
    NNode * Search(PNList plist,int key);
    
    //判空
    bool IsEmpty(PNList plist);
    
    //删除plist中的第一个key,有可能需要修改头指针,会出现二级指针
    bool DeleteVal(PNList *pplist,int key);
    
    //获取数据长度
    int GetLength(PNList plist);
    
    //输出所有数据
    void Show(PNList plist);
    
    //清空数据,需要修改头指针,会出现二级指针
    void Clear(PNList *pplist);
    
    //销毁动态内存,需要修改头指针,会出现二级指针
    void Destroy(PNList *pplist);

    创建nlist.cpp文件

    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>
    #include "nlist.h"
    
    //初始化函数,将头指针置NULL,会出现二级指针
    void InitList(PNList *pplist)
    {
     assert(pplist != NULL);
     if(pplist == NULL)
      return;
      
     *pplist = NULL;
    }
    
    //头插,需要修改头指针,会出现二级指针
    bool Insert_head(PNList *pplist,int val)
    {
     NNode *p = (NNode *)malloc(sizeof(NNode));
     p->data = val;
     if(IsEmpty(*pplist))
     {
      p->next = p;
      *pplist = p;
     }
     else
     {
      NNode *q;//找尾巴
      for(q=*pplist;q->next!=*pplist;q=q->next);
      p->next = *pplist;
      *pplist = p;
      q->next = p;
     }
     
     return true;
    }
    
    //尾插,有可能需要修改头指针,会出现二级指针
    bool Insert_tail(PNList *pplist,int val)
    {
     NNode *p = (NNode *)malloc(sizeof(NNode));
     p->data = val;
     if(IsEmpty(*pplist))
     {
      p->next = p;
      *pplist = p;
     }
     else
     {
      NNode *q;//找尾巴
      for(q=*pplist;q->next!=*pplist;q=q->next);
      q->next=p;
      p->next=*pplist;
     }
     
     return true;
    }
    
    //在plist中查找关键字key,找到返回节点,失败返回NULL
    NNode * Search(PNList plist,int key)
    {
     NNode *q;
     for(q=plist;q->next!=plist;q=q->next)
     {
      if(q->data==key)
      {
       return q;
      }
     }
     if(q->data==key)
     {
      return q;
     }
     
     return NULL;
    }
    
    //判空,判断plist是否为NULL
    bool IsEmpty(PNList plist)
    {
     return plist == NULL;
    }
    
    //删除plist中的第一个key,有可能需要修改头指针,会出现二级指针
    bool DeleteVal(PNList *pplist,int key)
    {
     if(IsEmpty(*pplist))
     {
      return false;
     }
     NNode *p;
     NNode *q;
     for(q=*pplist;q->next!=*pplist;q=q->next)
     {
      if(q->next->data==key)
      {
       p=q->next;
       q->next=q->next->next;
       free(p);
       
       return true;
      }
     }
     
     p=*pplist;
     if(p->data==key)
     {
      *pplist=p->next;
      q->next=*pplist;
      free(p);
      
      return true;
     }
     
     return false;
    }
    
    //获取数据长度
    int GetLength(PNList plist)
    {
     int count=1;
     for(NNode *q=plist;q->next!=plist;q=q->next)
     {
      count++;
     }
     return count;
    }
    
    //输出所有数据
    void Show(PNList plist)
    {
     if(IsEmpty(plist))
      return ;
     NNode *p=plist;
     for(;p->next!=plist;p=p->next)//bug
     {
      printf("%d ",p->data);
     }
     printf("%d \n",p->data);
    }
    
    //清空数据,需要修改头指针,会出现二级指针
    void Clear(PNList *pplist)
    {
     *pplist=NULL;
    }
    
    //销毁动态内存,需要修改头指针,会出现二级指针
    void Destroy(PNList *pplist)
    {
     NNode *p;
     NNode *q=*pplist;
     while(q->next!=*pplist)
     {
      p=q->next;
      q->next=p->next;
      free(p);
     }
     *pplist=NULL;
    }
    展开全文
  • 本片接上篇【数据结构:链表】——无头单向非循环链表的实现(C语言) 1、链表实现 带头双向循环链表带头双向循环链表:结构最复杂,一般用单独存储数据。实际中使用链表数据结构,都是带头双向 循环链表...

    本片接上一篇【数据结构:链表】——无头单向非循环链表的实现(C语言)

    1、链表实现

    带头双向循环链表: 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向
    循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而
    简单了,后面我们代码实现了就知道了。
    在这里插入图片描述

    2、代码实现

    从上图我们可以看出双向链表的节点数据结构就有了些许不同,一个节点有两个指针域和一个数据域组成,两个指针域一个是指向节点前一个prev前驱指针一个是指向节点后一个
    next指针,而循环也就说明了该链表左后一个节点不是指向NULL,而是指向头结点,而头结点的前驱同时也就指向位节点。
    链表节点数据结构定义:

    typedef int LTDateType;
    
    typedef struct ListNode//链表节点结构体
    {
    	LTDateType val;
    	struct ListNode *_prev;
    	struct ListNode *_next;
    }ListNode;
    
    typedef struct List//链表头结构体
    {
    	ListNode *_head;
    }List;
    

    解释一下在节点结构声明完成后为什么还要再声明一个结构;因为方便在对链表进行操作,防止二级指针操作失误。链表的操作都是用指针来完成的当传入链表的头结点就要传该节点的地址就要用二级指针,而声明结构体后就完美的解决了传二级指针的问题了。
    【注意】:这里不给出头文件,读者自己加上
    List.h文件

    void ListInit(List* plt);//初始化
    void ListDestory(List* plt);//销毁链表
    void ListPushBack(List* plt, LTDateType x);//尾部插入
    void ListPopBack(List* plt);//尾部删除
    void ListPushFront(List* plt, LTDateType x);//头部插入
    void ListPopFront(List* plt);//头部删除
    ListNode* BuyNode(LTDateType x);//创建一个链表节点
    ListNode* ListFind(List* plt, LTDateType x);//查找链表位置
    void ListInsert(ListNode* pos, LTDateType x);//在pos的前面插入
    void ListErase(ListNode* pos);//删除pos节点
    void ListPrint(List* plt);//输出链表
    

    List.c

    #define _CRT_SECURE_NO_WARNINGS 1
    #include"List.h"
    
    ListNode* BuyNode(LTDateType x)//创建一个链表节点
    {
    	ListNode *p = (ListNode*)malloc(sizeof(ListNode));
    	assert(p);
    	p->val = x;
    	p->_next = NULL;
    	p->_prev = NULL;
    
    	return p;
    }
    
    void ListInit(List* plt)//初始化
    {
    	assert(plt);
    	plt->_head = BuyNode(0);/头结点 不存任何值
    	plt->_head->_next = plt->_head;
    	plt->_head->_prev = plt->_head;
    }
    
    void ListPushBack(List* plt, LTDateType x)//尾部插入
    {
    	assert(plt);
    	ListNode *head = plt->_head;
    	ListNode *next = head->_prev;
    	ListNode *newnode = BuyNode(x);
    
    	next->_next = newnode;
    	head->_prev = newnode;
    
    	newnode->_prev = next;
    	newnode->_next = head;
    }
    
    void ListPopBack(List* plt)//尾部删除
    {
    	assert(plt);
    
    	ListNode *head = plt->_head;
    	ListNode *prev = head->_prev->_prev;
    	ListNode *tail = head->_prev;
    
    	prev->_next = head;
    	head->_prev = prev;
    	free(tail);
    	tail = NULL;
    
    }
    
    void ListPushFront(List* plt, LTDateType x)//头部插入
    {
    	assert(plt);
    
    	ListNode *head = plt->_head;
    	ListNode *next = head->_next;
    	ListNode *newnode = BuyNode(x);
    
    	newnode->_next = next;
    	next->_prev = newnode;
    
    	head->_next = newnode;
    	newnode->_prev = head;
    }
    
    void ListPopFront(List* plt)//头部删除
    {
    	assert(plt);
    
    	ListNode *head = plt->_head;
    	ListNode *next = head->_next;
    	ListNode *cur = next->_next;
    
    	head->_next = cur;
    	cur->_prev = head;
    	free(next);
    	next = NULL;
    
    }
    
    ListNode* ListFind(List* plt, LTDateType x)//查找链表位置
    {
    	assert(plt);
    
    	ListNode* head = plt->_head;
    	ListNode* cur = head->_next;
    
    	while (cur != head)
    	{
    		if (cur->val == x)
    		{
    			return cur;
    		}
    
    		cur = cur->_next;
    	}
    	return NULL;
    }
    
    void ListInsert(ListNode* pos, LTDateType x)//在pos的前面插入
    {
    	assert(pos);
    
    	ListNode* newnode = BuyNode(x);
    	ListNode* prev = pos->_prev;
    
    	newnode->_next = pos;
    	pos->_prev = newnode;
    
    	prev->_next = newnode;
    	newnode->_prev = prev;
    }
    
    void ListErase(ListNode* pos)//删除pos节点
    {
    	assert(pos);
    
    	ListNode* prev = pos->_prev;
    	ListNode* next = pos->_next;
    
    	prev->_next = next;
    	next->_prev = prev;
    	free(pos);
    	pos = NULL;
    }
    
    void ListPrint(List* plt)//输出链表
    {
    	ListNode *head = plt->_head;
    	ListNode *cur =head->_next;
    
    	printf("head");
    	while (cur != head)
    	{
    		printf("<=>%d", cur->val);
    		cur = cur->_next;
    	}
    	printf("\n");
    }
    

    main.c文件

    #define _CRT_SECURE_NO_WARNINGS 1
    #include"List.h"
    
    int main()
    {
    	Test()
    {
        List pl;
    	ListInit(&pl);
    	ListPushBack(&pl, 1);
    	ListPushBack(&pl, 2);
    	ListPushBack(&pl, 3);
    	ListPushBack(&pl, 4);
    	ListPushBack(&pl, 5);
    	ListPushBack(&pl, 6);
    	ListPrint(&pl);
    	
    	ListNode* pos_1 = ListFind(&pl, 4);
    	ListInsert(pos_1, 50);
    	ListPrint(&pl);
    
    	ListNode* pos_2 = ListFind(&pl, 50);
    	ListErase(pos_2);
    	ListPrint(&pl);
    
    	ListPushFront(&pl, 0);
    	ListPrint(&pl);
    	ListPopFront(&pl);
    	ListPrint(&pl);
    	ListPopBack(&pl);
    	ListPopBack(&pl);
    	ListPrint(&pl);
    }
    	system("pause");
    	return 0;
    }
    

    运行截图
    运行截图

    展开全文
  • 上一节里实现的是最简单的链表实际中那种链表不会单独用来存储数据,更多是作为其他数据结构的子结构,如图的邻接表等...如普通链表要访问最后的元素时,只能通过遍历链表来取得,而这可以直接取头节点的...

    上一节里实现的是最简单的链表,在实际中那种链表不会单独用来存储数据,更多是作为其他数据结构的子结构,如图的邻接表等。而比较常用的就是带头双向循环链表。
    在这里插入图片描述
    在这里插入图片描述
    通过对比我们可以看出有三个不同,多了头节点,链表中的元素之间不再是单向而是双向,头尾节点相连,构成循环链表。
    虽然结构比起之前的复杂了一点,但是优势却十分明显。
    如普通链表要访问最后的元素时,只能通过遍历链表来取得,而这个可以直接取头节点的前一个来找到尾巴。链表之间是双向的,所有可以实现回溯等操作。多了头节点可以直接在头节点上对链表就行修改,不需要再使用二级指针等

    数据结构
    typedef struct ListNode
    {
    	DATATYPE data;
    	struct ListNode* next;
    	struct ListNode* prev;
    }ListNode;
    

    我们需要用到两个指针,一个指向当前位置的前面,一个指向后面

    实现的接口
    // 创建返回链表的头结点.
    ListNode* ListCreate();
    // 双向链表销毁
    void ListDestory(ListNode* list);
    // 双向链表打印
    void ListPrint(ListNode* list);
    // 双向链表尾插
    void ListPushBack(ListNode* list, DATATYPE x);
    // 双向链表尾删
    void ListPopBack(ListNode* list);
    // 双向链表头插
    void ListPushFront(ListNode* list, DATATYPE x);
    // 双向链表头删
    void ListPopFront(ListNode* list);
    // 双向链表查找
    ListNode* ListFind(ListNode* list, DATATYPE x);
    // 双向链表在pos的前面进行插入
    void ListInsert(ListNode* pos, DATATYPE x);
    // 双向链表删除pos位置的节点
    void ListErase(ListNode* pos);
    

    创建返回链表的头结点

    ListNode* ListCreate()
    {
    	ListNode* head = (ListNode*)malloc(sizeof(ListNode));
    	head->data = 0;
    	head->next = head;
    	head->prev = head;
    	return head;
    }
    

    我们首先要创建头节点
    在这里插入图片描述
    在一开始我们就要确保双向循环,所以前后指针都指向自己

    在pos的前面进行插入

    我先不讲头插和尾插,而是直接讲插入,因为当我们能实现在pos位置插入时,就可以通过这个函数来实现头插和尾插

    在这里插入图片描述
    在这里插入图片描述
    如图,如果我们要让他在pos前面插入,就必须先让cur处理好他与pos的prev的关系,因为如果我们先让他变成pos的前一个,那么原本的前一个节点的位置就会丢失,所以我们必须要注意好顺序

    void ListInsert(ListNode* pos, DATATYPE x)
    {
    	assert(pos);
    
    	ListNode* cur = (ListNode*)malloc(sizeof(ListNode));
    	cur->data = x;
    
    	pos->prev->next = cur;
    	cur->prev = pos->prev;
    	cur->next = pos;
    	pos->prev = cur;
    
    	
    }
    

    头插

    void ListPushFront(ListNode* list, DATATYPE x)
    {
    	assert(list);
    
    	ListNode* head = list;
    	ListNode* tail = head->prev;
    	ListNode* cur = (ListNode*)malloc(sizeof(ListNode));
    	cur->data = x;
    
    	cur->next = head->next;
    	head->next->prev = cur;
    	
    	head->next = cur;
    	cur->prev = head;
    	
    	//ListInsert(list->next, x);
    }
    

    这里的实现思路一样,要处理好head的下一个节点与cur的关系,我们也可以用刚刚的插入函数直接实现,插入的位置就是头节点的下一个位置

    尾插

    void ListPushBack(ListNode* list, DATATYPE x)
    {
    	assert(list);
    
    	ListNode* head = list;
    	ListNode* tail = head->prev;
    	ListNode* cur = (ListNode*)malloc(sizeof(ListNode));
    	cur->data = x;
    
    	cur->prev = tail;
    	cur->next = head;
    	tail->next = cur;
    	head->prev = cur;
    
    	//ListInsert(list, x);
    }
    

    这里与前两个一样,就不罗嗦了,这里也可以用之前的函数,插入位置就是list也就是头节点,头节点的前一个位置就是尾节点,在这插入就是尾插

    删除pos位置的节点

    删除的操作和插入的思路基本一样,就不多说了

    void ListErase(ListNode* pos)
    {
    	assert(pos);
    
    	pos->next->prev = pos->prev;
    	pos->prev->next = pos->next;
    	free(pos);
    }
    

    头删

    void ListPopFront(ListNode* list)
    {
    	assert(list);
    	ListNode* head = list;
    	ListNode* next = head->next;
    	next->next->prev = head;
    	head->next = next->next;
    	free(next);
    	//ListErase(list->next);
    }
    

    尾删

    void ListPopBack(ListNode* list)
    {
    	assert(list);
    	ListNode* head = list;
    	ListNode* tail = list->prev;
    
    	head->prev = tail->prev;
    	tail->prev->next = head;
    	free(tail);
    	//ListErase(list->prev);
    }
    

    打印链表

    遍历输出即可

    void ListPrint(ListNode* list)
    {
    	assert(list);
    	ListNode* cur = list->next;
    	while (cur != list)
    	{
    		printf("%d ", cur->data);
    		cur = cur->next;
    	}
    	printf("NULL\n");
    }
    

    查找链表

    ListNode* ListFind(ListNode* list, DATATYPE x)
    {
    	assert(list);
    	ListNode* cur = list->next;
    
    	while (cur != list)
    	{
    		if (cur->data == x)
    			return cur;
    		else
    			cur = cur->next;
    	}
    
    	return NULL;
    }
    

    销毁链表

    void ListDestory(ListNode* list)
    {
    	assert(list);
    	
    	ListNode* head = list;
    	ListNode* cur = list->next;
    
    	while (cur != head)
    	{
    		ListNode* next = cur->next;
    		free(cur);
    		cur = next;
    	}
    
    	free(head);
    	head = NULL;
    
    }
    

    在这里插入图片描述
    完整代码
    头文件

    #pragma once
    #include<stdio.h>
    #include<assert.h>
    #include<stdlib.h>
    #define _CRT_SECURE_NO_WARNINGS
    #define LISTSIZE 10
    
    typedef int DATATYPE;
    
    typedef struct ListNode
    {
    	DATATYPE data;
    	struct ListNode* next;
    	struct ListNode* prev;
    }ListNode;
    
    // 创建返回链表的头结点.
    ListNode* ListCreate();
    // 双向链表销毁
    void ListDestory(ListNode* list);
    // 双向链表打印
    void ListPrint(ListNode* list);
    // 双向链表尾插
    void ListPushBack(ListNode* list, DATATYPE x);
    // 双向链表尾删
    void ListPopBack(ListNode* list);
    // 双向链表头插
    void ListPushFront(ListNode* list, DATATYPE x);
    // 双向链表头删
    void ListPopFront(ListNode* list);
    // 双向链表查找
    ListNode* ListFind(ListNode* list, DATATYPE x);
    // 双向链表在pos的前面进行插入
    void ListInsert(ListNode* pos, DATATYPE x);
    // 双向链表删除pos位置的节点
    void ListErase(ListNode* pos);
    

    函数实现

    #include "Double-linked circular list.h"
    
    ListNode* ListCreate()
    {
    	ListNode* head = (ListNode*)malloc(sizeof(ListNode));
    	head->data = 0;
    	head->next = head;
    	head->prev = head;
    	return head;
    }
    
    void ListPrint(ListNode* list)
    {
    	assert(list);
    	ListNode* cur = list->next;
    	while (cur != list)
    	{
    		printf("%d ", cur->data);
    		cur = cur->next;
    	}
    	printf("NULL\n");
    }
    
    void ListPushBack(ListNode* list, DATATYPE x)
    {
    	assert(list);
    
    	ListNode* head = list;
    	ListNode* tail = head->prev;
    	ListNode* cur = (ListNode*)malloc(sizeof(ListNode));
    	cur->data = x;
    
    	cur->prev = tail;
    	cur->next = head;
    	tail->next = cur;
    	head->prev = cur;
    
    	//ListInsert(list, x);
    }
    
    void ListPushFront(ListNode* list, DATATYPE x)
    {
    	assert(list);
    
    	ListNode* head = list;
    	ListNode* tail = head->prev;
    	ListNode* cur = (ListNode*)malloc(sizeof(ListNode));
    	cur->data = x;
    
    	cur->next = head->next;
    	head->next->prev = cur;
    	
    	head->next = cur;
    	cur->prev = head;
    	
    	//ListInsert(list->next, x);
    }
    
    void ListDestory(ListNode* list)
    {
    	assert(list);
    	
    	ListNode* head = list;
    	ListNode* cur = list->next;
    
    	while (cur != head)
    	{
    		ListNode* next = cur->next;
    		free(cur);
    		cur = next;
    	}
    
    	free(head);
    	head = NULL;
    
    }
    
    ListNode* ListFind(ListNode* list, DATATYPE x)
    {
    	assert(list);
    	ListNode* cur = list->next;
    
    	while (cur != list)
    	{
    		if (cur->data == x)
    			return cur;
    		else
    			cur = cur->next;
    	}
    
    	return NULL;
    }
    
    void ListInsert(ListNode* pos, DATATYPE x)
    {
    	assert(pos);
    
    	ListNode* cur = (ListNode*)malloc(sizeof(ListNode));
    	cur->data = x;
    
    	pos->prev->next = cur;
    	cur->prev = pos->prev;
    	cur->next = pos;
    	pos->prev = cur;
    
    	
    }
    
    void ListErase(ListNode* pos)
    {
    	assert(pos);
    
    	pos->next->prev = pos->prev;
    	pos->prev->next = pos->next;
    	free(pos);
    }
    
    void ListPopBack(ListNode* list)
    {
    	assert(list);
    	ListNode* head = list;
    	ListNode* tail = list->prev;
    
    	head->prev = tail->prev;
    	tail->prev->next = head;
    	free(tail);
    	//ListErase(list->prev);
    }
    
    void ListPopFront(ListNode* list)
    {
    	assert(list);
    	ListNode* head = list;
    	ListNode* next = head->next;
    	next->next->prev = head;
    	head->next = next->next;
    	free(next);
    	//ListErase(list->next);
    }
    
    展开全文
  • 题目是这样: 设以不带头结点的循环链表表示队列,并且只设一个指针指向队尾结点,但不设头指针。编写相应入队和出队程序。 如果带头尾指针那就很简单了,不带头尾指针只能函数中新建工作指针来操作。 思考...

    循环链表的入队出队

    题目是这样的: 设以不带头结点循环链表表示队列,并且只设一个指针指向队尾结点,但设头指针。编写相应的入队和出队程序。

    如果带头尾指针那就很简单了,不带头尾指针只能在函数中新建工作指针来操作。

    思考方向

    队列嘛,先进先出,用循环链表存储,再有个尾指针,逻辑结构就是这样的在这里插入图片描述

    入队

    入队分三步:
    新结点指向头结点在这里插入图片描述

    尾结点指向新节点
    在这里插入图片描述

    尾指针指向新的尾结点在这里插入图片描述

    出队

    先进先出嘛,头结点删了就行
    理论上直接尾结点指向第二个就完事了
    但这样只是找不到了原来的头结点,它依然是存在于内存中的,虽说眼不见为净吧在这里插入图片描述,但它确确实实是存在的,一旦堆积,这队列容量就会越来越小。
    所以还是要把它删除掉的(delete)在这里插入图片描述

    具体代码

    存储数据就以int为例,其他的自己适应性更改就行
    结点

    struct Node{
    	int data;
    	Node* next;
    };//创建结构体——结点
    

    循环队列

    class CirQueue {
    private:
    	Node* p;
    public:
    	CirQueue();
    	CirQueue(int a[], int n);
    	void EnQueue(int a);
    	void DeQueue();
    };
    CirQueue::CirQueue() {
    	p = nullptr;
    }
    CirQueue::CirQueue(int a[], int n) {
    	p = new Node;
    	p->data = a[0];
    	Node* q = p;//存储首地址,用于最后尾巴指过来
    	for (int i = 1; i < n; i++) {
    		p->next = new Node;
    		p = p->next;
    		p->data = a[i];		
    	}
    	p->next = q;
    }//初始化循环队列
    

    入队

    void CirQueue::EnQueue(int a) {
    	Node* q = new Node;
    	q->data = a;
    	q->next = p->next;//第一步
    	p->next = q;//第二步
    	p = q;//第三步
    	cout << a << "已入队,当前队列为:" << endl;
    	do {
    		q = q->next;
    		cout << q->data << '\t';
    	} while (q != p);
    	cout << '\n';
    }
    

    出队

    void CirQueue::DeQueue() {
    	Node* q = p->next;
    	p->next = p->next->next;
    	cout << q->data << "已删除,当前队列为:" << endl;
    	delete q;
    	q = p;
    	do {
    		q = q->next;
    		cout << q->data << '\t';
    	} while (q != p);
    	cout << '\n';
    }
    

    运行结果:在这里插入图片描述
    完。

    展开全文
  • 单循环链表与单链表的区别就是,单循环链表的尾指针指向头结点,可以想象成一个环,首尾相连,这时候需要考虑两种情况: 1.不带头结点 2.带头节点 不带头节点的情况: 对比单链表,直接尾结点的指针指向头节点就好了...
  • 一、 双向循环链表 带头双向循环链表是链表中结构较为复杂一种,一般用单独存储数据。... 首先,顾名思义,一个双向链表的节点中有一个数据域和两个指针域,其一个指针(next)指向后继,另一个指针(prior)指...
  • 链表的基本操作

    2018-09-19 17:08:15
    带头节点的单链表、带头节点的双向循环链表 链表:一种链式存储的线性表,用一组地址任意的存储单元存放线性表的数据元素,称存储单元为一个节点 链表分类 1./双链表 2.带/不带头节点 3.循环/不循环...
  • 已建有一个单循环链表带头结点),first 指向头结点。设 立两个工作指针 p 和 q,分别指向头结点和第 1 个结点;执行 q->prior=p;,建立第 1 个结点前驱指针,如图 1-4 所示;同步移动工作指针 p 和
  • 循环链表简介 将单链表中的终端节点的指针端由空指针改为指向头...提示:可以考虑用一个,不带头结点的循环链表来处理 Josephu 问题:先构成一个有n个结点的单循环链表,然后由k结点起从1开始计数,计到m时,对应结点从
  • Day04单向环形链表

    2020-04-06 13:19:36
    单向环形链表 Josephu(约瑟夫)问题 Josephu问题为:设编号为1,2,3,…,n的n个人围坐在一全圈,约定编号为k(1&...提示:用一个带头节点的循环链表来处理Josephu问题:先构成一个有n个节点单循环链表,然后由k节...
  • PHP链表

    2017-03-03 09:23:09
    链表链表是节点的集合.每一个节点通过链表相互连接,节点可以存储任何数据结构和内容。...链表无非是几种固定形式:单向的,双向的,循环的,带或不带头节点的,带或不带尾节点的,熟悉一种结构,其它...
  • 链表错题集

    2020-12-07 21:21:45
    带头结点的单循环链表中,任一结点的后继结点的指针域均不空。 T F 答案T:尾指针指针域为头结点,即均不为空 1-14 线性表若采用链式存储结构时,要求内存中可用存储单元的地址一定不连续。 T F 答案F:可连续,可不...
  • 提示:用一个带头节点的循环链表来处理约瑟夫问题:先构成一个有n个接待你的单循环链表,然后由k节点起从1开始计数,计到m时 对应节点从链表中删除,然后从被删除节点的下一个节点又从1开始技术,直到最后一...
  • 题目:约瑟夫环问题模拟。 问题描述:设编号为1,2,…,n(n>0)的n个人按顺时针方向围坐一圈,每人持有一个...(1)把带头节点的单循环链表设计为头文件。 (2)把带头节点的单循环链表作为存储结构。 测试数据:
  • A 单链表 B 仅有头指针的单循环链表 C 双链表 D 仅有尾指针的单循环链表 注意涉及到删除节点需要知道当前节点的前驱节点,一般是否使用双链表看是否有删除操作,是否是循环看对头尾节点的操作 带头结点的双循环链表L...
  • 约瑟夫游戏

    2019-10-08 17:51:19
    约瑟夫游戏 题目 约瑟夫实验,共有n个人围成一个圆桌,...主要就是不带头节点的单循环链表的实现,以及删除链表中某一个结点 代码(源码点击这里) 这里就不展示代码,想看源码的同仁可以点击上面的按钮哈。 ...
  • 数据结构之单链表

    2020-04-01 15:16:56
    链表 Linked list 有序的列表,内存中的存储方式为链式存储,即可以不用位置相连续 ...链表分为带头节点的链表和没有头节点的链表 链表分为 单向链表 循环链表 双向链表 单链表 方向的链表结构...
  • 分析:用一个带头结点的循环列表处理:先构成一个有n个节点的单循环链表,然后从K节点开始计数,记到m时,对应节点从链表中删除,然后从被删除节点的下一个节点又从一开始计数,直到最后一个节点从链...
  • Java–单向环形链表 Josepfu(约瑟夫环) 问题 已知n个人(以编号1,2,3...n分别表示)围坐... 解决方案:用一个带头的循环环形链表来处理Josepfu问题:先构成一个有n个节点的单循环链表,然后由K起点从1开始计数...
  • 若某表最常用操作是最后一个结点之后插入一个节点或删除最后一二个结点,则采用()省运算时间。 A. 单链表 B. 双链表 C. 单循环链表 D. 带头结点双循环链表 答案:D 解析:单链表和双链表每次找到尾部都需要...
  • 约瑟夫环 OJ

    2018-10-13 10:43:02
    循环链表的应用,并且应为不带头节点的循环链表,首先创建一个循环链表函数JOHEPHUS中进行操作,主要就是用for找到要删除的元素(注意p==1单独考虑,for中p至少为2),删除元素并输出直至链表为空。 for(j=1;j&...
  • 数据结构问题集锦

    2010-06-27 23:38:00
    1. 选首领。N个人围成一圈,从第一个开始报数数:1,2,3。凡报到3者退出圈子,最后留圈子里...(单循环链表)2. 用带头结点单链表表示两个一元多项式相乘,链表中的节点按幂指数降序排列;3. 就地倒置单链表; ...
  • (2018)设一个带头结点单链表L,数据元素为整数,其中大部分为正数,少数为负数,编写函数,采用高效算法调整链表,实现负结点移到链表的尾部,并返回调整后链表第一个负数节点位置。先给出算法思想,再写...
  • 2. (共15分)已知带头结点的单循环链表L,编写算法实现删除其中所有值为e 的数据元素结点。 (要求:类型定义、算法描述和算法时间复杂度分析) 类型定义:(3分) typedef struct LNode{ ElemType data; ...
  • //建立带头结点的单循环链表 void initRing(int n, LinkList &R) { ListNode *p, *rear; p = NULL; //构造一个空的循环列表 R = (LinkList)malloc(sizeof(ListNode)); //建立头结点 R->next = R; rear...
  • 数据结构(C++)有关练习题

    热门讨论 2008-01-02 11:27:18
    内容及步骤: 1、 设有一个线性表(e0,e1,e2,e3,…,en-2,en-1)存放在一个一维数组A[arraySize]中前n个数组元素位置。请编写一个函数将这个线性表原地逆置,即将数组前n个原地址内容置换为(en-1,en-2,…,e3,...

空空如也

空空如也

1 2
收藏数 27
精华内容 10
关键字:

在一个带头节点的单循环链表