复习之数据结构_带头结点的循环单链表

循环单链表简单理解

前面复习了单链表,单链表的尾结点的特点是next域为NULL(空);而我们今天要复习的循环单链表,和单链表基本类似。
区别就在于:
循环单链表的尾结点的next域为头结点

头文件(.h)

老规矩,先上头文件:
笔者这里的命名为:clist.h

#pragma once
// 带头结点的循环单链表
// 尾结点的next指向头结点

typedef struct CNode
{
    
    
	int data;			// 保存数据
	struct CNode* next;  // 下一个结点
}CNode, * CList;

// 初始化函数
void InitList(CList plist);

// 判空
bool IsEmpty(CList plist);

// 获取数据长度
int GetLength(CList plist);

// 头插
bool Insert_head(CList plist, int val);

// 尾插
bool Insert_tail(CList plist, int val);

// 在plist中查找关键字key,找到返回目标地址,失败返回NULL
CList Search(CList plist, int key);

// 删除plist中的第一个key
bool DeleteVal(CList plist, int key);

// 打印输出所有数据
void Show(CList plist);

// 逆置(重中之重)
void Reverse(CList plist);

// 清空数据
void Clear(CList plist);

// 销毁动态内存
void Destroy(CList plist);

代码文件(.cpp)

接下来是代码文件,命名为clist.cpp

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "clist.h"

// 初始化函数
void InitList(CList plist)
{
    
    
	assert(plist != NULL);
	if (plist == NULL) return;

	// 使其成为环
	plist->next = plist;
}

// 判空
bool IsEmpty(CList plist)
{
    
    
	assert(plist != NULL);

	return plist->next == plist;
}

// 获取数据长度
int GetLength(CList plist)
{
    
    
	assert(plist != NULL);

	int count = 0;
	for (CNode* p = plist->next; p != plist; p = p->next)
	{
    
    
		count += 1;
	}
	return count;
}

// 头插
bool Insert_head(CList plist, int val)
{
    
    
	assert(plist != NULL);

	CNode* p = (CNode*)malloc(sizeof(CNode));
	
	p->data = val;

	p->next = plist->next;
	plist->next = p;

	
	return true;
}

// 尾插
bool Insert_tail(CList plist, int val)
{
    
    
	assert(plist != NULL);

	// 创建新结点
	CNode* p = (CNode*)malloc(sizeof(CNode));
	// 给新结点赋值val
	p->data = val;

	// 让q定位到最后一个数据结点
	CNode* q;
	for (q = plist->next; q->next != plist; q = q->next)
	{
    
    
		// 不用做操作
		;
	}
	//p->next = q->next;与下方语句等价
	p->next = plist;
	q->next = p;

	return true;
}

// 在plist中查找关键字key,找到返回目标地址,失败返回NULL
CList Search(CList plist, int key)
{
    
    
	assert(plist != NULL);

	// 需要注意如果初始化为plist->next
	// 则控制语句不能是:p->next != plist
	for (CNode* p = plist->next; p != plist; p = p->next)
	{
    
    
		if (key == p->data)
		{
    
    
			return p;
		}
	}
	return NULL;
}

// 查找key的前驱结点,成功返回key的前驱,失败返回NULL
// static关键字修饰全局函数:只能在本文件使用
static CNode* SearchPrio(CList plist, int key)
{
    
    
	assert(plist != NULL);

	// 注意:此处起始条件p初始化成头结点
	for (CNode* p = plist; p->next != plist; p = p->next)
	{
    
    
		if (key == p->next->data)
		{
    
    
			return p;
		}
	}
	return NULL;
}

// 删除plist中的第一个key
bool DeleteVal(CList plist, int key)
{
    
    
	assert(plist != NULL);

	CNode* p = SearchPrio(plist, key);
	// 如果找到了即p不空
	if (p)
	{
    
    
		// 先用q指向我们要删除的结点
		CNode* q = p->next;
		// 随后把q剔除
		p->next = q->next;
		// 释放内存,完成删除
		free(q);

		return true;
	}
	else
	{
    
    
		printf("未查找到您要删除的结点,删除失败\n");
		return false;
	}
}

// 打印输出所有数据
void Show(CList plist)
{
    
    
	assert(plist != NULL);

	for (CNode* p = plist->next; p != plist; p = p->next)
	{
    
    
		printf("%d ",p->data);
	}
	printf("\n");
}

// 逆置(重中之重)
void Reverse(CList plist)
{
    
    
	assert(plist != NULL);
	
	// 运用头插的思想
	CNode* p = plist->next;
	CNode* q;

	plist->next = plist;

	while (p != plist)
	{
    
    
		q = p->next;

		//将p头插到plist中
		p->next = plist->next;
		plist->next = p;
		p = q;
	}
}

// 清空数据
void Clear(CList plist)
{
    
    
	assert(plist != NULL);

	plist->next = plist;
}

// 销毁动态内存
void Destroy(CList plist)
{
    
    
	assert(plist != NULL);

	CNode* p;
	// 只要存在数据结点
	while (plist->next != plist)
	{
    
    
		// p指向第一个数据结点
		p = plist->next;
		// 把第一个结点剔除
		plist->next = p->next;
		free(p);
	}
}

代码测试

如下代码简单测试一下我们写的函数:

#include <stdio.h>
#include <iostream>
#include "clist.h"

int main()
{
    
    
	CNode head;
	InitList(&head);
	for (int i = 0; i < 5; i++)
	{
    
    
		Insert_tail(&head,i);
	}
	Show(&head);
	printf("逆置后:\n");
	Reverse(&head);
	Show(&head);
	printf("目前链表长度:%d\n", GetLength(&head));
	printf("删除第一个\"0\"后\n");
	DeleteVal(&head, 0);
	Show(&head);
	printf("目前链表长度:%d\n", GetLength(&head));
	Destroy(&head);

	return 0;
}

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

参考资料

【1】严蔚敏. 数据结构(C语言版). 北京:清华大学出版社,2009:30.

猜你喜欢

转载自blog.csdn.net/m0_46308273/article/details/114122568