数据结构与算法(C语言)------循环链表1

循环链表

一、定义

将单链表中终端结点的指针端由空指针改为指向链表的第一个结点,这就使单链表形成一个环,这种头尾相接的单链表称为循环链表(circular linked list)。循环链表相对于单向链表的最大优点在于:通过链表中任意的结点地址便可遍历整个链表。

二、代码(不含头结点)

#ifndef __CIRCULARLINKEDLIST_H
#define __CIRCULARLINKEDLIST_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_SIZE 30
#define OK     1
#define ERROR  0

typedef int states;

typedef struct {
	int id;
	char name[MAX_SIZE];
}ElementType;

/** 循环链表结点结构 */
typedef struct cirNode{
	ElementType data;          //数据域
	struct cirNode *next;      //指针域
}CirNode;

/** 循环链表表头结构 */
typedef struct {
	CirNode *headptr;
	int length;
}CircularLinkedList;

/** 初始化循环链表 */
states InitCircularLinkedList(CircularLinkedList *ptrl);

/** 向循环链表中插入元素(按位置下标) */
states InsertCircularLinkedList(CircularLinkedList *ptrl,int pos,ElementType x);

/** 从循环链表中删除元素(按照位置下标删除) */
states DeleteCirLinkedList(CircularLinkedList *ptrl,int pos,ElementType *x);

/** 获取循环链表结点个数 */
int GetCirLinkedListLength(CircularLinkedList *ptrl);

/** 清空循环链表 */
states ClearCirLinkedList(CircularLinkedList *ptrl);

/** 根据元素内容返回链表中相应结点地址 */
states GetCirNodePtr(CircularLinkedList *ptrl,ElementType x,CirNode **nodeptr);

/** 通过某一结点地址,遍历整个循环链表 */
states PrintfCirListByNodeptr(CircularLinkedList *ptrl,CirNode *nodeptr);

/** 打印循环链表 */
void PrintfCirLinkedList(CircularLinkedList *ptrl);

#endif /*__CIRCULARLINKEDLIST_H */

#include "circularlinkedlist.h"

/** 初始化循环链表 */
states InitCircularLinkedList(CircularLinkedList *ptrl)
{
	ptrl->headptr = NULL;
	ptrl->length = 0;
	return OK;
}

/** 向循环链表中插入元素(按位置下标插入) */
states InsertCircularLinkedList(CircularLinkedList *ptrl,int pos,ElementType x)
{
	int i;
	CirNode *newNode, *tempNode;
	//判断输入的pos范围是否正确
	if(pos < 1 || pos > ptrl->length + 1)
		return ERROR;
	newNode = (CirNode *)malloc(sizeof(CirNode));
	newNode->data = x;
	newNode->next = NULL;
	//分情况讨论
	if(pos == 1){
		//pos == 1时,需要考虑改变链表末尾结点next指针的指向
		newNode->next = ptrl->headptr;
		ptrl->headptr = newNode;
		ptrl->length++;
		tempNode = ptrl->headptr;
		for(i = 1;i < ptrl->length;i++){
			tempNode = tempNode->next;
		}
		tempNode->next = ptrl->headptr;
		return OK;
	}
	tempNode = ptrl->headptr;
	for(i = 1;i < pos - 1;i++){
		tempNode = tempNode->next;
	}
	newNode->next = tempNode->next;
	tempNode->next = newNode;
	ptrl->length++;
	return OK;
}

/** 从循环链表中删除元素(按照位置下标删除) */
states DeleteCirLinkedList(CircularLinkedList *ptrl,int pos,ElementType *x)
{
	int i;
	CirNode *delNode, *tempNode;
	//判断循环链表是否为空
	if(!ptrl->headptr || ptrl->length == 0)
		return ERROR;
	//判断输入的pos变量范围是否正确
	if(pos < 1 || pos > ptrl->length)
		return ERROR;
	//分两种情况进行讨论
	if(pos == 1){
		//需要考虑改变链表中最后一个结点的next指针指向
		delNode = ptrl->headptr;
		ptrl->headptr = delNode->next;
		ptrl->length--;
		*x = delNode->data;
		free(delNode);
		tempNode = ptrl->headptr;
		for(i = 1;i < ptrl->length;i++){
			tempNode = tempNode->next;
		}
		tempNode->next = ptrl->headptr;
		return OK;
	}
	tempNode = ptrl->headptr;
	for(i = 1;i < pos - 1;i++){
		tempNode = tempNode->next;
	}
	delNode = tempNode->next;
	tempNode->next = delNode->next;
	*x = delNode->data;
	free(delNode);
	ptrl->length--;
	return OK;
}

/** 获取循环链表结点个数 */
int GetCirLinkedListLength(CircularLinkedList *ptrl)
{
	return ptrl->length;
}

/** 清空循环链表 */
states ClearCirLinkedList(CircularLinkedList *ptrl)
{
	CirNode *p,*q;
	p = ptrl->headptr;
	if(!p)                //链表为空,退出
		return ERROR;
	while(p->next != ptrl->headptr){
		q = p->next;
		free(p);
		p = q;
	}
	free(p);
	ptrl->headptr =NULL;
	ptrl->length = 0;
	return OK;
}

/** 根据元素内容返回链表中相应结点地址 */
states GetCirNodePtr(CircularLinkedList *ptrl,ElementType x,CirNode **nodeptr)
{
	int i;
	CirNode *node = ptrl->headptr;
	for(i = 0;i < ptrl->length;i++){
		if(x.id == node->data.id)
		{
			if(strcmp(x.name,node->data.name) == 0)
			{
				*nodeptr = node;
				return OK;
			}		
		}
		node = node->next;
	}
	return ERROR;
}

/** 通过某一结点地址,遍历整个循环链表 */
states PrintfCirListByNodeptr(CircularLinkedList *ptrl,CirNode *nodeptr)
{
	CirNode *tempNode = nodeptr;
	while(tempNode->next != nodeptr){
		printf("[%d %s] ",tempNode->data.id,tempNode->data.name);
		tempNode = tempNode->next;
	}
	printf("[%d %s] ",tempNode->data.id,tempNode->data.name);
	return OK;
}

/** 打印循环链表 */
void PrintfCirLinkedList(CircularLinkedList *ptrl)
{
	int i;
	CirNode *node = ptrl->headptr;
	for(i = 0;i < ptrl->length;i++){
		printf("[%d %s] ",node->data.id,node->data.name);
		node = node->next;
	}

}

三、编程笔记

  • 循环链表与单链表的代码的不同点
    1、链表最后一个结点的指针域要指向链表的第一个结点地址。
    2、循环链表遍历的结束条件改变。whie(node->next != ptrl->headptr); 跳出循环条件的为链表最后一个结点的地址。
  • 向循环链表中插入元素(按位置下标插入)
    1、判断输入的pos范围是否正确;(1 - ptrl->length + 1)
    2、建立将要插入循环链表的结点。
    3、分情况讨论
    pos == 1时,插入的位置为1时,需要改变ptrl->headptr变量的值,又因为是循环链表,考虑链表的最后一个结点的指针域要指向链表的第一个结点地址。
    pos > 1时,操作与单链表相同。找到位于pos - 1位置的结点地址。插入新建结点,注意结点指针域的改变顺序。
  • 从循环链表中删除元素(按照位置下标删除)
    1、判断链表是否为空。
    2、判断输入的pos范围是否正确。(1 - ptrl->length)
    3、分情况讨论
    pos == 1时,删除第一个结点之后,ptrl->headptr 和链表最后结点的指针域要改变。并将删除结点的数据域取出。
    pos > 1时,与单链表的删除操作相同。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据结构和算法是计算机科学中非常重要的概念。数据结构是为解决实际问题而设计的,用于存储和组织数据的方式。它可以分为逻辑结构和物理结构。逻辑结构包括集合结构、线性结构、树形结构和图形结构,而物理结构则包括顺序存储和链式存储。 算法则是解决问题的一系列步骤或操作。它具有输入、输出、有穷性、确定性和可行性这五个基本特性。算法是在数据结构上操作的过程,通过对数据结构的操作实现问题的解决。 在C语言中,我们可以使用不同的数据结构和算法来解决问题。例如,队列是一种常用的数据结构,它可以使用链表来实现,其中包括头结点和尾结点。队列可以进行插入和删除操作,通常使用头尾指针来指示队列的状态。循环队列是一种特殊的队列,当队列满时,头指针会指向尾指针的下一个位置,而当队列为空时,头指针和尾指针指向同一个位置。 另一个常用的数据结构是栈,它具有先进后出的特性。栈的应用包括前缀、中缀和后缀表达式的计算。在这些表达式中,运算符的优先级决定了计算的顺序。前缀表达式将运算符放在操作数之前,后缀表达式将运算符放在操作数之后,而中缀表达式则是我们日常生活中最常见的形式。 综上所述,数据结构和算法是C语言中解决问题的重要工具。我们可以根据问题的特点选择合适的数据结构和算法来实现解决方案。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [数据结构和算法(C语言)](https://blog.csdn.net/weixin_60096751/article/details/123643490)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [C语言数据结构与算法](https://blog.csdn.net/Syext/article/details/129896715)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值