精华内容
下载资源
问答
  • C++实现的带头结点的双向循环链表, 数据结构课设.。
  • 判断表是否为空,如果为空则返回true,不空返回false. 给出表中数据元素的个数。 给定一个索引(位置),返回指向该位置的数据元素的指针,如果给定的位置号不合法,则返回空指针。 给定数据元素x,如果表中有该元素...
  • 本文实例讲述了Python双向循环链表实现方法。分享给大家供大家参考,具体如下: 最近身边的朋友在研究用python来实现数据结构。遇到一个问题就是双向循环链表的实现,改指向的时候总是发蒙。 我自己尝实现了一个...
  • 文章不空谈理论,完全采用手把手教学,并有综合示例练习题,看完这篇,你绝对能掌握数据结构双向循环链表

    一、双向循环链表

    双向循环链表

    二、用C语言实现双向循环链表

    1、构造存储结构
    typedef int datatype;
    
    typedef struct doublelist{
          datatype data;
          struct doublelist *next, *prev;
    }double_list, *double_plist;
    
    2、初始化

    初始化主要工作:①申请头结点内存空间;②head->next = head; head->prev = head;

    初始化

    3、插入结点

    (1)、向p指向的结点后面插入new指向的结点
    在这里插入图片描述

    步骤①:new->next = p->next;
    步骤②:p->next->prev = new;
    步骤③:new->prev =p;
    步骤④:p->next = new;

    /* 向p指向的结点后面插入new指向的结点 */
    void insert_doublelist_behind(double_plist p, double_plist new)
    {
          new->next = p->next;
          p->next->prev = new;
          new->prev = p;
          p->next = new;
    }
    

    (2)、向p指向的结点前面插入new指向的结点

    在这里插入图片描述

    步骤①:new->prev = p->prev;
    步骤②:p->prev->next = new;
    步骤③:new->next = p;
    步骤④:p->prev = new;

    /* 向p指向的结点前面插入new指向的结点 */
    void insert_doublelist_tail(double_plist p, double_plist new)
    {
          new->prev = p->prev;
          p->prev->next = new;
          new->next = p;
          p->prev = new;
    }
    
    4、删除结点

    (1)、删除p指向的结点后面的结点
    在这里插入图片描述

    t = p->next;
    p->next = t->next;
    t->next->prev = p;
    free(t);

    /* 删除p指向的结点后面的结点 */
    void delete_doublelist_post(double_plist p)
    {      
          double_plist t = NULL;
          
          t = p->next;
          p->next = t->next;
          t->next->prev = p;
          free(t);
    }
    

    (2)、删除p指向的结点前面的结点
    在这里插入图片描述

    t = p->prev;
    p->prev = t->prev;
    t->prev->next = p;
    free(t);

    /* 删除p指向的结点前面的结点 */
    void delete_doublelist_prev(double_plist p)
    {
          double_plist t = NULL;
    
          t = p->prev;
          p->prev = t->prev;
          t->prev->next = p;
          free(t);
    }
    

    (3)、删除p指向的结点
    在这里插入图片描述

    p->prev->next = p->next;
    p->next->prev = p->prev;
    free(p);

    /*  删除p指向的结点*/
    void delete_doublelist(double_plist p)
    {
          p->prev->next = p->next;
          p->next->prev = p->prev;
          free(p);
    }
    
    5、判断链表是否为空

    判断head->next == head 是否成立即可。

    /* 判断链表是否为空 */
    bool isempty_doublelist(double_plist head)
    {
          if (head == head->next)
          {
                return true;
          }
          else
          {
                return false;
          }  
    }
    
    6、打印链表
    void show_doublelist(double_plist head)
    {
          double_plist p = NULL;
    
          for (p = head->next; p != head; p = p->next)
          {
                printf("%d\t", p->data);
          }
          printf("\n");
    }
    

    三、练习题

    用双向循环链表实顺序递增存储若干自然数,比如输入一个整数10,则建立一个双向循环链表,里面的每个节点分别存放1,2,3,4,5,6,7,8,9,10,然后通过某些操作,将其重新排列成1,3,5,7,9,10,8,6,4,2,即奇数升序偶数降序,并在屏幕上打印出来。

    1、创建链表
    /* 创建链表 */
    void create_doublelist(double_plist head)
    {
          int n = 0;
          int i = 0;
          double_plist new = NULL;
    
          printf("请输入要插入的数据个数:");
          scanf("%d", &n);
    
          for (i=0; i<n; i++)
          {
                new = (double_plist)malloc(sizeof(double_list));
                if (NULL == new)
                {
                      perror("malloc");
                      exit(1);
                }
                printf("输入要插入的第%d个数据:", i+1);
                scanf("%d", &(new->data));
    
                /* 使用前插方法 */
                insert_doublelist_tail(head, new);
                show_doublelist(head);
          }
    }
    
    2、排序
    /* 排序 */
    void sort_doublelist(double_plist head)
    {
          double_plist p = NULL;
          double_plist t = NULL;
    
          p = head->prev;   /* p指向最后那个结点,从后往前找 */
          while (p != head)
          {
                if (1 == (p->data % 2))    /* 判断是否为奇数 */
                {
                      p = p->prev; /* 如果是奇数,p往前移 */
                }
                else  /* 偶数 */
                {
                      t = p; /* 保存这个结点的数据 */
                      p = p->prev; /* p继续往前移 */
                      delete_doublelist(t);   /* 删除这个结点,但不释放它,还继续保存数据 */
                      insert_doublelist_tail(head, t); /* 将t结点作为新结点插入到head结点后面 */
                      show_doublelist(head);
                }
                
          }
    }
    
    3、main函数
    int main(void)
    {
          double_plist head = NULL;
    
          init_doublelist(&head);
          create_doublelist(head);
          sort_doublelist(head);
    
          return 0;
    }
    
    4、实验结果

    在这里插入图片描述

    四、完整代码

    https://github.com/sanjaywu/DataStructure

    展开全文
  • 每日一句 It’s gonna be ok. ... 跟单向链表类似,我们既可以初始化一个带有头结点的空循环链表,也可以不要头结点: 这边把两个步骤放在一起了 linklist init_list(void) // 带有头结点的单循环链表 { linklis

    每日一句

    It’s gonna be ok.

    一切都会好的。

    内容概要

    单向循环链表

    首先来看看图示:
    单链表

    图展示的是一个单向循环链表,他跟以上的单向链表对比只是多了一个指向头结点的 指针,因此,他们的算法几乎是一样的。
    第一,设计节点。 单向循环链表的节点跟单向链表完全一致。

    第二,初始化空链表。 跟单向链表类似,我们既可以初始化一个带有头结点的空循环链表,也可以不要头结点:
    头节点

    这边把两个步骤放在一起了

    linklist init_list(void) // 带有头结点的单循环链表 
    { 
    	linklist head = malloc(sizeof(listnode)); 
    	head->next = head;
    	return head; 
    }
    

    然后就是插入节点的操作,跟单链表一样,可以去看我前面的文章,链接https://blog.csdn.net/qq_41835250/article/details/107568684

    第三,由于单循环链表的特点,删除一个指定的节点时我们可以不需要头指针,而仅仅通过该 待删除节点的指针就可以回溯到他的前一个节点,进而实现删除操作:

    void remove_node(linklist delete) 
    { 
    	linklist tmp = delete; 
    	while(tmp->next != delete) // 从 delete开始,绕一圈找到其前面的节点
    	{ 
    		tmp = tmp->next;
    	}
    	tmp->next = delete->next; 
    	delete->next = NULL;
    }
    

    第四,移动节点。 在单链表中,移动节点需要三个参数,因为移动的目的地可能在原始位置的前面,由于 没有头指针的情况下无法回溯回去,因此必须要链表的头指针来遍历。但是对于单循环链表
    而言则不存在这个问题,链表中的任意一个节点,都可以从另一个任意节点出发找到,因此 移动节点不需要三个参数,请看代码:

    void move_node(linklist p, linklist anchor) 
    { 
    	if(p == NULL || anchor == NULL) 
    	return;
    	remove_node(p); // 先将要移动的节点从链表中剔除 
    	insert_node(anchor, p); // 再插入指定的地方
    }
    

    第五,查找节点。 同理,单循环链表的查找跟单链表的查找基本是一样的,只是在判断是否遍历完链表的 条件上有所差别:

    linklist find_node(linklist mylist, int data) 
    { 
    	if(is_empty(mylist)) 
    		return NULL;
    	linklist tmp;
    	for(tmp=mylist->next; tmp!=mylist; tmp=tmp->next) 
    	{
    		if(data == tmp->data) 
    			break; 
    	} 
    	return tmp==mylist ? NULL : tmp; // 如果遍历回到 mylist 则表示找不到
    }
    

    双向循环链表

    通过上面的内容,可以看出来单循环链表的缺点就是每一次遍历都需要从头开始,不能从任意位置来遍历,于是双向循环链表的出现就是来解决这个问题的。
    第一,设计节点。 双向链表的节点当然需要两个指针,节点的设计如下:
    双链表

    typedef struct node
    {
    	int data;
    	struct node *prev;
    	struct node *next;
    }listnode, *linklist;
    

    这里需要注意一下,:节点中的 prev 和 next 指针均是 struct node 型的指针,他们都是指向本结 构体类型的相邻节点的。
    第二,初始化空链表。
    因为一般情况下我们所使用的大都是带头结点的双向循环链表,所以我就直接使用带头结点的。

    linklist init_list(void)
    {
    	linklist mylist = malloc(sizeof(listnode));
    	if(mylist != NULL)
    	{
    		mylist->prev = mylist->next = mylist;
    	}
    	return mylist;
    }
    

    第三,插入节点
    由于双向循环链表的特征,所以可以有两种插入方式,头插法和尾插法,先来看看头插法的图示步骤:
    头插法
    第 1 步,将新节点的 prev 指针指向 anchor 节点:new->prev = anchor
    第 2 步,将新将节点的 next指向 anchor 下一个节点:new->next = anchor->next
    第 3 步,将节点 anchor 的 next 指针指向新节点 new:anchor->next = new
    第 4 步,将 anchor 原来的下一个节点的 prev 指针指向 new 节点: new->next->prev = new
    把它们链接起来就是

    void insert_next(linklist new, linklist anchor) 
    { 
    	if(new == NULL || anchor == NULL) 
    		return;
    	new->prev = anchor; // 第①步 
    	new->next = anchor->next; // 第②步
    	
    	anchor->next = new; // 第③步 
    	new->next->prev = new; // 第④步
    }
    

    尾插法也类似,不过是把节点插在头节点的后面
    还是画个图示:
    尾插法
    步骤:
    第 1 步,将新节点的 prev 指向 anchor 的前节点:new->prev = anchor->prev
    第 2 步,将新节点的 next 指向 anchor:new->next = anchor
    第 3 步,将 anchor 的前节点的 next 指向新节点:anchor->prev->next = new
    第 4 步,将 anchor 的前驱指针指向 new:anchor->prev = new;
    代码:

    void insert_prev(linklist new, linklist anchor)
    { 
    	if(new == NULL || anchor == NULL) 
    		return;
    	new->prev = anchor->prev; 
    	new->next = anchor;
    	new->prev->next = new;
    	anchor->prev = new;
    }
    

    第四,删除节点。
    删除一个节点的步骤很简单,只需要将其前趋节点指向其后续节点,将其后续节点指向其前驱节点即可,另外要注意,需将被删除节点的前后向指针置空,使其彻底从链表中脱离 开来,防止错误的访问。

    void remove_node(linklist delete) 
    { 
    	if(delete == NULL) 
    		return;
    	delete->prev->next = delete->next;  delete->next->prev = delete->prev; 
    	delete->prev = NULL;  
    	delete->next = NULL; //这两行代码用来将要删除的节点彻底脱离
    }
    

    第五,移动节点。
    移动节点很好理解,就是一个删除一个移动,画个图就很好理解
    移动节点
    代码

    void move_next(linklist p, linklist anchor) 
    { 
    	remove_node(p); // 将要移动的节点从链表中移除
    	insert_next(p, anchor); // 将节点插入锚点 anchor 的后面 
    }
    

    第六,查找节点。 节点的查找无非就是对链表进行遍历,从头开始找,找一圈找到为止。直接上代码:

    linklist find_node(int data, linklist mylist)
    {
    	if(is_empty(mylist))
    		return NULL;
    
    	linklist tmp = mylist->next;  // 让 tmp从第一个节点开始
    
    
    	while(tmp != mylist)
    	{
    		if(tmp->data == data)
    			return tmp;
    
    		tmp=tmp->next; // 不断地向后遍历,查找
    
    	}
    	return NULL;
    }
    

    如果看到这里你都已经基本看明白了,那么你用双向循环链表写一个学生管理系统什么的已经没问题了,以前我也是学到这里也做过,如果需要欢迎私信。
    写到这里突然想起来Linux里还有一个叫做内核链表的东西,下一篇更新一下内核链表。
    每一个功能我都写成函数以便于调用,如有问题,欢迎指正。
    感谢观看。

    展开全文
  • C语言实现双向循环链表

    千次阅读 2019-09-24 20:15:30
    以三个节点例,双向循环链表结构如上图所示。每个节点都分为数据域和指针域,数据域是存储数据的;指针域存储前向指针和后向指针,前向指针指向该节点的上一个节点,后向指针指向该节点的下一个节点。循环链表是指...

    C语言实现双向循环链表(附有源码)

    一、双向循环链表的结构

    在这里插入图片描述

    以三个节点为例,双向循环链表结构如上图所示。每个节点都分为数据域和指针域,数据域是存储数据的;指针域存储前向指针和后向指针,前向指针指向该节点的上一个节点,后向指针指向该节点的下一个节点。循环链表是指首尾要相连,即第一个节点的前向指针指向最后一个节点,最后一个节点的后向指针指向第一个节点,形成一个环。

    二、实现一个双向循环链表

    1. 首先创建一个双向循环链表的节点
    typedef struct Node
    {
    	int data;
    	struct Node *Next;
    	struct Node *Pre;
    }NODE, *HNODE;
    
    2. 创建链表的菜单项、初始化、增、删、改、查等函数
    //操作菜单
    void menuDisplay(){
    
    	printf("菜单\n");
    	printf("*****************************\n");
    	printf("1、进入系统	0\n");
    	printf("2、创建链表	1\n");
    	printf("3、添加节点	2\n");
    	printf("4、删除节点	3\n");
    	printf("5、更改节点	4\n");
    	printf("6、查找数据	5\n");
    	printf("7、打印链表	6\n");
    	printf("8、删除链表	7\n");
    	printf("9、退出系统	8\n");
    	printf("*****************************\n");
    }
    //创建双向循环链表
    HNode CreateLinkNode(void)
    {
    	int i, length = 0, data = 0;
    	HNode p_new = NULL, pTail = NULL;
    	HNode head = (HNode)malloc(sizeof(NODE));
     
    	if (NULL == head)
    	{
    		printf("内存分配失败!\n");
    		exit(EXIT_FAILURE);
    	}
    	head->data = 0;
    	head->next= head;
    	head->pre= head;
    	pTail = head;
     
    	printf("请输入想要创建链表的长度:");
    	scanf("%d", &length);
     
    	for (i=1; i<length+1; i++)
    	{
    		p_new = (HNode)malloc(sizeof(NODE));
     
    		if (NULL == p_new)
    		{
    			printf("内存分配失败!\n");
    			exit(EXIT_FAILURE);
    		}
     
    		printf("请输入第%d个节点元素值:", i);
    		scanf("%d", &data);
     
    		p_new->data = data;
    		p_new->pre= pTail;
    		p_new->next= head;
    		pTail->next= p_new;
    		head->pre= p_new;
    		pTail = p_new;
    	}
    	return head;
    }
    
    //打印链表
    void PrintfLinkNode(HNode head)
    {
    	HNode pt = head->next;
     
    	printf("链表打印结果为:");
    	while (pt != head)
    	{
    		printf("%d ", pt->data);
    		pt = pt->next;
    	}
    	putchar('\n');
    }
    //查找数据
    void searchLinkNode(HNode head, int data){
    	HNode pt = head->next;
    	int i =1 ,m=0;
     
    	while (pt != head)
    	{
    		if(pt->data==data){
    			printf("第%d个位置上为:%d\n",i,pt->data);
    			m++;
    		}
    		pt = pt->next;
    		i++;
    	}
    	if(m==0){
    		printf("没有找到该数据!");
    	}else{
    		printf("一共找到%d个数据",m);
    	}
    	m=0;
    	putchar('\n');
    
    }
     
    //判断链表是否为空
    int IsEmpty(HNode head)
    {
    	HNode pt = head->next;
     
    	if (pt == head)
    		return 1;
    	else
    		return 0;
    }
     
    //计算链表长度
    int LinkNodeLength(HNode head)
    {
    	int length = 0;
    	HNode pt = head->next;
     
    	while (pt != head)
    	{
    		length++;
    		pt = pt->next;
    	}
    	return length;
    }
    //插入节点
    int InsertLinkNode(HNode head, int pos, int data)
    {
    	HNode p_new = NULL, pt = NULL;
    	if (pos > 0 && pos < LinkNodeLength(head) + 2)
    	{
    		p_new = (HNode)malloc(sizeof(NODE));
     
    		if (NULL == p_new)
    		{
    			printf("内存分配失败!\n");
    			exit(EXIT_FAILURE);
    		}
     
    		while (1)
    		{
    			pos--;
    			if (0 == pos)
    				break;
    			head = head->next;
    		}
    		
    		p_new->data = data;
    		pt = head->next;
    		p_new->next= pt;
    		p_new->pre= head;
    		head->next= p_new;
    		pt->pre= p_new;
    		
    		return 1;
    	}
    	else
    		return 0;
    }
    
    //删除节点
    int	DeleteLinkNode(HNode head, int pos)
    {
    	HNode pt = NULL;
    	if (pos > 0 && pos < LinkNodeLength(head) + 1)
    	{
    		while (1)
    		{
    			pos--;
    			if (0 == pos)
    				break;
    			head = head->next;
    		}
    		pt = head->next->next;
    		free(head->next);
    		head->next= pt;
    		pt->pre= head;
     
    		return 1;
    	}
    	else
    		return 0;	
    }
     //更改链表中某节点的值
    int AlterEleDbCcLinkList(HNode head, int location, int value){
    	int i = 0;
    	DeleteLinkNode(head, location);
    	i = InsertLinkNode(head, location,value);
    	return i;
    }
    //删除整个链表,释放内存空间
    void FreeMemory(HNode *head)
    {
    	HNode pt = NULL;
    	while (*head != NULL)
    	{
    		pt = (*head)->next->next;
     
     
    		if ((*head)->next== *head)
    		{
    			free(*head);
    			*head = NULL;
    		}
    		else
    		{
    			free((*head)->next);
    			(*head)->next= pt;
    			pt->pre= *head;
    		}
    	}
    }
    
    3.主函数
    int main(void)
    {
    	int flag = 0, length = 0;
    	int position = 0, value = 0,data=0,length2=0,flag2=0;
    	HNode head = NULL;
    	int menuNumber,input=-1;
    	menuDisplay();
    	while(1){
    		scanf("%d",&input);
    		if(input==0){
    				printf("您已进入系统!\n");
    		
    		while(1){
    			printf("请输入与操作对应的数字:");
    			scanf("%d",&menuNumber);
    		if(menuNumber==1){
    			flag2=1;
    			head = CreateLinkNode();
    			flag = IsEmpty(head);
    			if (flag)
    				printf("双向循环链表为空!\n");
    			else
    			{
    				length = LinkNodeLength(head);
    				printf("双向循环链表的长度为:%d\n", length);
    				PrintfLinkNode(head);
    			}
    		}
    		if(flag2!=0){
    			if(menuNumber==2){
    				length2 = LinkNodeLength(head);
    				if(length2==0){
    					printf("双向循环链表为空!\n");
    				
    				}else{
    						printf("请输入要插入节点的位置和元素值(两个数用空格隔开):");
    					scanf("%d %d", &position, &value);
    					flag = InsertLinkNode(head, position, value);
    					if (flag)
    					{
    						printf("插入节点成功!\n");
    						PrintfLinkNode(head);
    					}	
    					else
    						printf("插入节点失败!\n");
    				}
    
    			}
    			if(menuNumber==3){
    						flag = IsEmpty(head);
    				if (flag)
    					printf("双向循环链表为空,不能进行删除操作!\n");
    				else
    				{
    					printf("请输入要删除节点的位置:");
    					scanf("%d", &position);
    					flag = DeleteLinkNode(head, position);
    					if (flag)
    					{
    						printf("删除节点成功!\n");
    						PrintfLinkNode(head);
    					}	
    					else
    						printf("删除节点失败!\n");
    				}
    			}
    			if(menuNumber==4){
    				printf("请输入要更改节点的位置和元素值(两个数用空格隔开):");
    				scanf("%d %d", &position, &value);
    					flag = AlterEleDbCcLinkList(head, position, value);
    				if (flag)
    				{
    					printf("更改节点成功!\n");
    					PrintfLinkNode(head);
    				}	
    				else
    					printf("更改节点失败!\n");
    			
    			}
    			if(menuNumber==5){
    					printf("请输入要查找的数据:");
    					scanf("%d", &data);
    					searchLinkNode(head,data);
    
    			}
    			if(menuNumber==6){
    							
    			PrintfLinkNode(head);
    			
    			}
    			if(menuNumber==7){
    							
    				FreeMemory(&head);
    				if (NULL == head)
    					printf("已成功删除双向循环链表,释放内存完成!\n");
    				else
    					printf("删除双向循环链表失败,释放内存未完成!\n");
    			
    			}
    			if(menuNumber==8){
    				printf("您已退出系统!\n");
    				menuDisplay();
    				break;
    			}
    		}else{
    		printf("请先创建一个链表!\n");
    
    		
    		}
    		
    	}	
    		}
    	
    	}
    
    	return 0;
    }
    
    
    4.结果展示

    结果如图:
    在这里插入图片描述

    程序源码:c语言双向循环链表

    提取码:w594

    展开全文
  • 双向循环链表,即每个节点都拥有一前一后两个指针且头尾互链的链表。各种链表的简单区别如下:单向链表:基本链表;单向循环链表:不同于单向链表以 NULL 判断链表的尾部,单向循环链表的尾部链接到表头,因此当迭代...
  • 数据结构c语言双向循环链表 双向循环链表在定义上类似于循环单链表,就多了个前指针,以方便于向前查找。在双向链表中需要同时修改两个方向的指针,是单向链表指针的两倍。 完整代码如下: #include <stdio.h>...

    数据结构c语言双向循环链表

    双向循环链表在定义上类似于循环单链表,就多了个前指针,以方便于向前查找。在双向链表中需要同时修改两个方向的指针,是单向链表指针的两倍。
    完整代码如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct DuLNode
    {
    	int data;//结点的数据域 
    	struct DuLNode *prior;//结点的后指针域 
    	struct DuLNode *next;//结点的前指针域 
    }DuLNode,*DuLinkList;//DuLinkList为指向结构体LNode的指针类型
    
    DuLNode* InitDuList()//初始化链表  构建一个空的线性表 
    {
    	DuLNode* L = (DuLNode*)malloc(sizeof(DuLNode));
    	if(L==NULL)//判断申请L结点是否为空 
    	{
    		printf("ERROR!\n");
    		return 0;
    	}
    	L->data = NULL;//定义头结点
    	L->next = L;
    	L->prior = L;
    }
    
    void Interrupt(void)//创建一个中断函数 
    {
    	while(1)//用于检测换行符,使函数脱离scanf的连续输出 
    		if(getchar()=='\n')
    			break;
    } 
    
    DuLinkList CreatDuList1(DuLinkList &L)//尾插法创建链表 
    {
    	int a,b,i;
    	DuLNode* p = L;//导入头结点,并创建一个结点s指向头结点 
    	printf("请输入表长: "); 
    	scanf("%d",&a);//输入要插入的链表长度 
    	Interrupt();//中断scanf 
    	printf("请输入表数据: ");
    	for(i=0;i<a;i++)
    	{
    		scanf("%d",&b);//输入要链表数据 
    		DuLNode* s = (DuLNode*)malloc(sizeof(DuLNode));//创建一个结点
    		s->data = b;
    		p->next = s;
    		s->prior = p;
    		s->next = L;
    		L->prior = s;
    		p = p->next;
    	}
    	Interrupt();
    	return 0;
    }
    DuLinkList CreatDuList2(DuLinkList &L)//头插法创建链表
    {
    	int a,b,i;
    	DuLNode* p = L;//导入头结点,并创建一个结点s指向头结点 
    	printf("请输入表长: "); 
    	scanf("%d",&a);//输入要插入的链表长度 
    	Interrupt();
    	printf("请输入表数据: ");
    	for(i=0;i<a;i++)
    	{
    		scanf("%d",&b);//输入要链表数据 
    		DuLNode* s = (DuLNode*)malloc(sizeof(DuLNode));//创建一个结点
    		s->data = b;
    		L->next = s;
    		s->prior = L;
    		s->next = p;
    		p->prior = s;
    		p = s;
    	}
    	Interrupt();
    	return 0;
    }
    int Length(DuLinkList L)//求链表长度 
    {
    	int i=0;
    	DuLNode* p = L;
    	while(1)//建立一个死循环,链表最后一个结点指向L(头结点),以此为判断break循环条件 
    	{
    		if(p->next == L)
    			break;
    		p = p->next;
    		i++;
    	} 
    	return i;//返回链表长度 
    }
    
    void TraverseDuLNode(DuLinkList L)//遍历链表,并输出链表
    {
    	DuLNode* p = L;//创建一个结点并指向头结点 
    	if(Length(L) == 0)//判断链表是否为空 
    	{
    		printf("空表\n");
    	}
    	else
    	{
    		while(1)//建立一个死循环,链表最后一个结点指向L(头结点),以此为判断break循环条件
    		{
    			p = p->next;
    			printf("%d  ",p->data);
    			if(p->next == L)//判断break循环条件
    				break; 
    		}
    		printf("\n");
    	}
    	
    }
    
    int LocateElem(DuLinkList L,int e)//按值查找操作。在表L中查找具有给定关键字值的元素 
    {
    	DuLNode* p = L;//创建一个结点并指向头结点 
    	int i=0; 
    	if(Length(L)==0)
    	{
    		printf("空表无法查询\n");
    		return 0;
    	}
    	else
    	{
    		bool a = true;//利用bool类型,来判断链表中是否存在要查找的值 
    		scanf("%d",&e);//要查找的值 
    		Interrupt();
    		while(1)//建立一个死循环,链表最后一个结点指向L(头结点),以此为判断break循环条件 
    		{
    			p = p->next;
    			i++;
    			if(p->data == e)
    			{
    				printf("第 %d 位  ",i);
    				a = false;
    			}
    			if(p->next == L)
    				break;
    		}
    		if(a)//链表中没有要查找的值 
    			printf("没找到!"); 
    		printf("\n");
    		return 0;
    	}
    }
    int GetElem(DuLinkList L,int i)//按位查找操作 
    {
    	if(Length(L) == 0)//判断链表是否为空 
    	{
    		printf("空表无法查询!\n");
    		return 0;
    	}
    	scanf("%d",&i);//输入要查找第几位 
    	Interrupt();
    	int j=0;
    	DuLNode* p = L;//创建一个结点并指向头结点 
    	if(i<1||i>Length(L))//判断输入的i值是否合理
    	{
    		printf("ERROR!\n");
    		return 0;
    	}
    	else
    	{
    		for( ;j<i;j++)//利用循环,是p结点指向第i位 
    			p = p->next;
    		printf("%d\n",p->data);
    		return 0;
    	}
    }
    int DuListInsert(DuLinkList &L,int i,int e)//插入操作
    {
    	int j;
    	DuLNode* p = L;//创建一个结点并指向头结点 
    	scanf("%d %d",&i,&e);//输入要插入链表的位置,和值  
    	Interrupt();                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
    	if(i<1||i>Length(L)+1)//判断插入链表的位置是否合理 
    	{
    		printf("ERROR!");
    		return 0;
    	}
    	else
    	{
    		DuLNode* s = (DuLNode*)malloc(sizeof(DuLNode));//创建一个新结点 
    		s->data = e;
    		for(j=1;j<i;j++)//利用循环,是p结点指向第i-1位
    			p = p->next;
    		p->next->prior = s;
    		s->next = p->next;
    		p->next = s;
    		s->prior = p;
    		printf("插入成功\n");
    	}
    }
    int DuListDelete(DuLinkList &L,int i)//删除操作 
    {
    	int j;
    	DuLNode* p = L;//创建一个结点并指向头结点 
    	scanf("%d",&i);//输入要删除链表的结点位置 
    	Interrupt();
    	if(Length(L)==0)//判断要删除的链表是否为空表 
    	{
    		printf("ERROR!\n");
    		return 0;
    	}
    	if(i<1||i>Length(L))//判断删除的结点位置是否合理 
    	{
    		printf("ERROR!\n");
    		return 0;
    	}
    	else
    	{
    		for(j=0;j<i;j++)//利用循环,是p结点指向第i位 
    			p = p->next;
    		p->prior->next = p->next;
    		p->next->prior = p->prior; 
    		printf("删除成功\n");
    		return 0; 		
    	}
    }
    int main()
    {
    	int a,b,i=0; 
    	char c;
    	DuLinkList L;//将L定义为LinkList类型的变量,便于直接引用 
    	L = InitDuList();
    	printf("输入0为尾插法(其他为头插法):"); 
    	scanf("%d",&b);
    	Interrupt();//中断scanf 
    	if(b==0)
    		CreatDuList1(L);//尾插法 
    	else
    		CreatDuList2(L);//头插法 
    	TraverseDuLNode(L);
    	printf("操作输入序号选择:\n 1:遍历链表\n 2:链表的按位查找\n 3:删除链表元素\n 4:插入链表元素\n 5:链表的按值查找\n 6:表长\n输入#退出\n");	
    	while(1)
    	{
    		int f = 0;
    		printf("请选择:"); 
    		scanf("%c",&c);
    		Interrupt();//中断scanf 
    		switch(c)
    		{
    			case '1': printf("遍历并输出链表: ");TraverseDuLNode(L); break;
    			case '2': printf("链表的按位查找(取值位置): ");GetElem(L,a); break;
    			case '3': printf("删除并返回要删除的元素(删除的位置): ");DuListDelete(L,a); break;
    			case '4': printf("插入元素(位置 插入的元素): ");DuListInsert(L,a,a); break;
    			case '5': printf("链表的按值查找(输入要查找的元素): ");LocateElem(L,a); break;
    			case '6': a = Length(L);printf("链表长为: %d\n",a); break;
    			case '#': f = 1; break;
    			default: printf("ERROR\n");
    		}
    		if (f == 1) 
    		{
    			printf("已正常退出!\n");
    			break;
    		}
    	}
    	free(L); 
    	return 0;
    } 
    

    (完)

    展开全文
  • C#双向循环链表

    2021-08-26 11:31:09
    双向循环链表跟单向循环链表差不多,多了一个指针。 部分代码可以优化:插入、删除、获取元素时可以根据count判断一下是前半部分还是后半部分,来决定是走Next还是Last。 节点类: /// <summary> /// 节点 //...
  • 线性表(List) 阜向循环链表一元多项式 双向循环链表 小结和作业 题讲解 单向循环链表 定义:最后一个结点的指针不是指针,而 是指向了头结点 逻辑形态 L 单向循环链表 差异 1判断空表的条件 L->next==NULL变为L->...
  • 双向循环链表 每个结点有两个指针域,分别指向前驱结点和后继结点,尾结点的后继指针指向头结点,头结点的前驱指针指向尾结点。整体形成一个双向连通的环。 创建一个结点类: class Node(object): """结点...
  • 设计算法,判断带头结点的循环双向链表是否对称 算法思路: ⚫ 建立两个工作指针p和q,p从左向右扫描L,q从右向左扫描L,两者同时扫描⚫ 进入while循环判断,若p与q不相等且p的后继不等于q ⚫ 若对应数据结点的data...
  • 双向循环链表实现(c语言)

    千次阅读 多人点赞 2018-12-20 09:44:41
    #include &amp;lt;stdio.h&amp;gt; #include &amp;lt;stdlib.h&amp;gt; typedef int ElemType; typedef struct node { ElemType data; struct node*next;...//链表初始化 linkList in...
  • 不带头结点的双向循环链表

    千次阅读 2019-05-21 18:46:36
    基本概念 循环链表:将单链表中最后一个结点的next指向头结点或者指针,就使得整个单链表形成一个环,这种头尾相接的单链表...双向循环链表:将二者结合起来,结点有两个指针域,且最后一个结点的next指向...
  • 单向循环链表和双向循环链表

    千次阅读 2019-11-25 11:58:10
    单向循环链表和双向循环链表1.单向循环链表2.双向循环链表 关于顺序表、单向链表和双向链表请将鼠标移步 此处点击 1.单向循环链表 代码实现: //#pragma once //作为头文件时加上这行 #include<stdio.h> #...
  • 双向循环链表的长度Problem statement: 问题陈述: Given a linked list, write a program that checks whether the given Linked List contains a loop or not and if the loop is present then return the count...
  • 头文件: #ifndef _LINKLIST_H #define _LINKLIST_H #define FAILURE 10000 #define SUCCESS 10001 #define TRUE 10002 #define FALSE 10003 ...typedef int ElemType;...struct node //双向循环链表 { ...
  • 单向循环链表 观察单向链表和单向循环链表的区别: 显然,循环链表和普通链表的区别在于,尾节点的next指针指向了头节点。而对于这条指向的维护也只在于add和remove方法,因此循环链表仅仅在这个方法上有所不同。...
  • =tail){ //这里因为不知道链表是奇数个还是偶数个所以两个条件都写上了 if(pre->data==tail->data){ pre=pre->next; tail=tail->prior; } } if(pre==tail||pre->next==tail){ //这里根据指针判断是否...
  • 双向循环链表的实现 (1)动态申请节点 在这里插入代码片
  • 一般来说, 链表我们用的最多的是不带头单向链表 和 带头双向循环链表。 所谓带头与不带头的区别在于头结点是否存储数据。 1、带头意味着头结点不会真正存放结点信息, 一般存放一些记账信息(例如链表多长等) 2、...
  • 双向循环链表

    2018-06-29 09:54:45
    /* 判断双向循环链表L是否为空:若L为空表,则返回TRUE,否则返回FALSE */ int TestListEmpty(DuLinkList L) { if(L->next == L && L->prior == L) return true; else return false; } /* 获取双向循环链表的...
  • 双向循环链表.cpp #include <stdio.h> #include <malloc.h> #include <assert.h> #include "dclist.h" /* 作业1:补全双向循环链表代码 作业2:单链表习题 */ //循环链表可执行的操作:(增删改...
  • is_empty() 链表是否为空 length() 链表长度 travel() 遍历链表 add(item) 链表头部添加 append(item) 链表尾部添加 insert(pos, item) 指定位置添加 remove(item) 删除节点 search(item) 查找节点是否存在 ...
  • 带头单向循环链表、带头单向非循环链表、带头双向循环链表、带头双向非循环链表、无头单向循环链表、无头单向非循环链表、无头双向循环链表、无头双向非循环链表。  在这八种结构中,我们只挑两种来进行刨析,即...
  • 利用双向循环链表表示一个整数序列,指定一个结点位置用p指向该结点,交换p所指向的结点及其前驱结点的顺序。 输入 多组数据,每组数据有三行,第一行为链表的长度n,第二行为链表的n个元素(元素之间用空格分隔)...
  • } 三、全部代码 //双向循环链表 #include #include //存储结构 typedef struct LNode { int data; struct LNode *next, *prior; }LNODE, * LINKLIST; //基本操作(14种) LINKLIST InitList(LINKLIST L); //创建 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 61,056
精华内容 24,422
关键字:

双循环链表判断为空