44 线性表

O( )表示法 时间复杂度 空间复杂度

#include<stdlib.h>
#include<stdio.h>
#include<string>


//算法最终编译成具体的计算机指令
//每一个指令,在具体的计算机上运行速度固定
//通过具体的n的步骤,就可以推导出算法的复杂度
long sum1(int n)	//2n+4	===>O(n)	空间复杂度 O(n)
{
	long ret = 0;	//1		4
	int* array = (int*)malloc(n * sizeof(int));//1	4n
	int i = 0;//1	4

	for (i = 0; i < n; i++)	//n
	{
		array[i] = i + 1;
	}

	for (i = 0; i < n; i++)	//n
	{
		ret += array[i];
	}

	free(array);	//1

	return ret;
}

long sum2(int n)	//n+2 ==>O(n)	空间复杂度O(1)
{
	long ret = 0;	//1		4
	int i = 0;	// 1		4

	for (i = 1; i <= n; i++)	//n
	{
		ret += i;
	}

	return ret;
}

long sum3(int n)	// 2	===>O(1)	空间复杂度O(1)
{
	long ret = 0;	// 1 4

	if (n > 0)		// 1
	{
		ret = (1 + n) * n / 2;
	}

	return ret;
}

int main()
{
	printf("%d\n", sum1(100));
	printf("%d\n", sum2(100));
	printf("%d\n", sum3(100));

	return 0;
}

O ( 1 ) < O ( l o g ( n ) ) < O ( n ) < O ( n 2 ) < O ( n 3 ) < O ( 2 n ) < O ( n ! ) < O ( n n ) O(1)<O(log(n))<O(n)<O(n^2)<O(n^3)<O(2^n)<O(n!)<O(n^n) O(1)<O(log(n))<O(n)<O(n2)<O(n3)<O(2n)<O(n!)<O(nn)

1 线性表

线性表(List)是零个或多个数据元素的集合

线性表中的数据元素之间是有顺序的

线性表中的数据元素个数是有限的

线性表中的数据元素的类型必须相同

1 线性表顺序存储

优点:

无需为线性表中的逻辑关系增加额外的空间

可以快速的获取表中合法位置的元素

缺点:

插入和删除操作需要移动大量元素

当线性表长度变化较大时难以确定存储空间的容量

C语言实现

seqlist.h

#ifndef __MY_SEQLIST_H__
#define __MY_SEQLIST_H__

typedef void SeqList;
typedef void SeqListNode;

// 创建并且返回一个空的线性表
SeqList* SeqList_Create(int capacity);

// 销毁一个线性表list
void SeqList_Destory(SeqList* list);

// 将一个线性表list中的所有元素清空,线性表回到创建时的初始状态
void SeqList_Clear(SeqList* list);

// 返回一个线性表list中的元素个数
int SeqList_Length(SeqList* list);

int SeqList_Capacity(SeqList* list);

// 向一个线性表list的pos位置中插入新元素node
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos);

// 获取一个线性表list的pos位置处的元素
SeqListNode* SeqList_Get(SeqList* list, int pos);

// 删除一个线性表list的pos处元素,返回值为被删除的元素,NULL表示删除失败
SeqListNode* SeqList_Delete(SeqList* list, int pos);

#endif 

seqlist.c

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include"seqlist.h"

//结构体套一级指针
typedef struct _tag_SeqList {
	int length;
	int capacity;
	// unsigned int* node;	// int *node[] 指针数组
    unsigned int ** node;
}TSeqList;

SeqList* SeqList_Create(int capacity) {
	TSeqList* tmp = NULL;
	tmp = (TSeqList*)malloc(sizeof(TSeqList));
	if (tmp == NULL) {
		printf("func SeqList_Create() error");
		return NULL;
	}

	memset(tmp, 0, sizeof(TSeqList));

	//根据capacity大小分配节点空间
//	tmp->node = (unsigned int*)malloc(sizeof(unsigned int*) * capacity);
    tmp->node = (unsigned int**)malloc(sizeof(unsigned int*) * capacity);
	if (tmp->node == NULL) {
		printf("func SeqList_Create()  tmp->node error  ");
		return NULL;
	}

	tmp->capacity = capacity;
	tmp->length = 0;

	return tmp;
}

// 销毁一个线性表list
void SeqList_Destory(SeqList* list) {
	TSeqList* tlist = NULL;
	if (list == NULL) {
		return;
	}
	tlist = (TSeqList*)list;
	if (tlist->node != NULL) {
		free(tlist->node);
	}
	free(tlist);
}

// 将一个线性表list中的所有元素清空,线性表回到创建时的初始状态
void SeqList_Clear(SeqList* list) {
	TSeqList* tlist = NULL;
	if (list == NULL) {
		return;
	}
	tlist = (TSeqList*)list;
	tlist->length = 0;
}

// 返回一个线性表list中的元素个数
int SeqList_Length(SeqList* list) {
	TSeqList* tlist = NULL;
	if (list == NULL) {
		return -1;
	}
	tlist = (TSeqList*)list;
	return tlist->length;
}

int SeqList_Capacity(SeqList* list) {
	TSeqList* tlist = NULL;
	if (list == NULL) {
		return -1;
	}
	tlist = (TSeqList*)list;
	return tlist->capacity;
}

// 向一个线性表list的pos位置中插入新元素node
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos) {
	int i = 0, ret = 0;
	TSeqList* tlist = NULL;
	if (list == NULL || node==NULL || pos < 0) {
		ret = -1;
		printf("SeqList_Insert() error : %d\n", ret);
		return ret;
	}

	tlist = (TSeqList*)list;

	//判断是不是链表空间满了
	if (tlist->length == tlist->capacity) {
		ret = -2;
		printf("SeqList_Insert() tlist->length == tlist->capacity error : %d\n", ret);
		return ret;

	}

	// 容错修正	长度为6,容量为20, 在pos=10插入,可以改为插入7位置
	if (pos >= tlist->length) {
		pos = tlist->length;
	}

	// 元素后移
	for (i = tlist->length; i > pos; i--) {
		tlist->node[i] = tlist->node[i-1];
	}
	// 元素插入
//	tlist->node[i] = (unsigned int*)node;
    tlist->node[i] = node;
	tlist->length++;
	return 0;
}

// 获取一个线性表list的pos位置处的元素
SeqListNode* SeqList_Get(SeqList* list, int pos) {
	int i = 0;
	SeqListNode* ret = 0;
	TSeqList* tlist = NULL;
	if (list == NULL ||  pos < 0) {
		printf("SeqList_Get() error : %d\n", ret);
		return NULL;
	}

	tlist = (TSeqList*)list;
	ret = (SeqListNode*)tlist->node[pos];
	return ret;
}

// 删除一个线性表list的pos处元素,返回值为被删除的元素,NULL表示删除失败
SeqListNode* SeqList_Delete(SeqList* list, int pos) {
	int i = 0;
	SeqListNode* ret = 0;
	TSeqList* tlist = NULL;
	if (list == NULL || pos < 0) {
		printf("SeqList_Delete() error : %d\n", ret);
		return NULL;
	}
	tlist = (TSeqList*)list;

	ret = (SeqListNode*)tlist->node[pos];

	for (i = pos + 1; i < tlist->length; i++) {
		tlist->node[i-1] = tlist->node[i];
	}
	tlist->length--;
	return ret;
}

main

#include<stdlib.h>
#include<stdio.h>
#include<string.h>	// c语言中要写.h,不然会报错
#include"seqlist.h"

typedef struct Teacher
{
	int age;
	char name[64];
}Teacher;

void main() {
	int ret = 0;
	int i = 0;
	SeqList* list = NULL;

	Teacher t1, t2, t3, t4, t5;
	t1.age = 21;
	t2.age = 22;
	t3.age = 23;
	t4.age = 24;
	t5.age = 25;

	list = SeqList_Create(10);
	if (list == NULL) {
		printf("func SeqList_Create() ret %d \n", ret);
		return ret;
	}

	ret = SeqList_Insert(list, (SeqListNode*)& t1, 0);	// 头插法
	ret = SeqList_Insert(list, (SeqListNode*)& t2, 0);	// 头插法
	ret = SeqList_Insert(list, (SeqListNode*)& t3, 0);	// 头插法
	ret = SeqList_Insert(list, (SeqListNode*)& t4, 0);	// 头插法
	ret = SeqList_Insert(list, (SeqListNode*)& t5, 0);	// 头插法

	// 遍历
	for (i = 0; i < SeqList_Length(list); i++) {
		Teacher* tmp = (Teacher*)SeqList_Get(list, i);
		if (tmp == NULL) {
			return;
		}
		printf("tmp->age:%d\n", tmp->age);
	}
	
	// 删除链表中节点
	while (SeqList_Length(list) > 0) {
		SeqList_Delete(list, 0);
	}
}

结果

tmp->age:25
tmp->age:24
tmp->age:23
tmp->age:22
tmp->age:21

2 线性表链式存储

采用通用链表的方式,用数据结构包含链表
blog.csdnimg.cn/d988ebafe9e14931b03633e79afc11b0.png#pic_center)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

1 单向链表

LinkList添加示意图

在这里插入图片描述

LinkList删除示意图
在这里插入图片描述

linklist.h

#ifndef _MYLINKLIST_H_
#define _MYLINKLIST_H_

typedef void LinkList;
/*
typedef struct _tag_LinkListNode LinkListNode;
struct _tag_LinkListNode{
	LinkListNode *next;
}

*/

typedef struct _tag_LinkListNode {
	struct _tag_LinkListNode* next;
}LinkListNode;

LinkList* LinkList_Create();

void LinkList_Destory(LinkList* list);

void LinkList_Clear(LinkList* list);

int LinkList_Length(LinkList* list);

int LinkList_Insert(LinkList* list, LinkListNode* node, int pos);

LinkListNode* LinkList_Get(LinkList* list, int pos);

LinkListNode* LinkList_Delete(LinkList* list, int pos); 

#endif

linklist.c

#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include"linklist.h"


typedef struct _tag_LinkList {
	LinkListNode head;
	int length;
}TLinkList;

LinkList* LinkList_Create() {
	TLinkList* ret = NULL;
	ret = (TLinkList*)malloc(sizeof(TLinkList));
	memset(ret, 0, sizeof(TLinkList));
	ret->length = 0;
	ret->head.next = NULL;
	
	return ret;
}

void LinkList_Destory(LinkList* list) {
	if (list != NULL) {
		free(list);
		list = NULL;
	}
	return;
}

// 让链表变为初始值
void LinkList_Clear(LinkList* list) {
	TLinkList* tList = 0;
	if (list == NULL) {
		return;
	}
	tList = (TLinkList*)list;

	tList->length = 0;
	tList->head.next = NULL;

	return;
}

int LinkList_Length(LinkList* list) {
	TLinkList* tList = 0;
	if (list == NULL) {
		return;
	}
	tList = (TLinkList*)list;
	return tList->length;
}

int LinkList_Insert(LinkList* list, LinkListNode* node, int pos) {
	int ret = 0, i = 0;
	TLinkList* tList = NULL;
	LinkListNode* current = NULL;

	if (list == NULL || node == NULL || pos < 0) {
		ret = -1;
		printf("LinkList_Insert error %d\n",ret); 
		return ret;
	}
	
	tList = (TLinkList*)list;
	current = &(tList->head);

	for (i = 0; i < pos && current->next != NULL; i++) {
		current = current->next;
	}
	// 1 node连接后续链表
	node->next = current->next;
	// 2 前面链表连接新的链表
	current->next = node;

	tList->length++;
	return ret;
}

LinkListNode* LinkList_Get(LinkList* list, int pos) {
	int i = 0;
	TLinkList* tList = NULL;
	LinkListNode* current = NULL;

	if (list == NULL || pos < 0) {
		printf("LinkList_Get error %d\n");
		return NULL;
	}

	tList = (TLinkList*)list;
	current = &(tList->head);	//辅助指针变量指向链表头部

	for (i = 0; i < pos && current->next != NULL; i++) {
		current = current->next;
	}
	return current->next;
}

LinkListNode* LinkList_Delete(LinkList* list, int pos) {
	int i = 0;
	TLinkList* tList = NULL;
	LinkListNode* current = NULL;
	LinkListNode* ret = NULL;

	if (list == NULL || pos < 0) {

		printf("LinkList_Delete error \n");
		return NULL;
	}

	tList = (TLinkList*)list;
	current = &(tList->head);

	for (i = 0; i < pos && current->next != NULL; i++) {
		current = current->next;
	}
	// 缓存被删除节点
	ret = current->next;
	current->next = ret->next; 

	tList->length--;
	return ret;
}

线性表链式存储继承测试.c

#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include"linklist.h"


typedef struct Teacher {
	LinkListNode node;
	int age;
	char name[32];
}Teacher;
void main() {
	int ret = 0, len = 0, i = 0;

	LinkList* list = NULL;

	Teacher t1, t2, t3, t4, t5;
	t1.age = 21;
	t2.age = 22;
	t3.age = 23;
	t4.age = 24;
	t5.age = 25;

	list = LinkList_Create();
	if (list == NULL) {
		return;
	}

	len = LinkList_Length(list);

	ret = LinkList_Insert(list, (LinkListNode*)& t1, 0);	//头插法
	ret = LinkList_Insert(list, (LinkListNode*)& t2, 0);	//头插法
	ret = LinkList_Insert(list, (LinkListNode*)& t3, 0);	//头插法
	ret = LinkList_Insert(list, (LinkListNode*)& t4, 0);	//头插法
	ret = LinkList_Insert(list, (LinkListNode*)& t5, 0);	//头插法

	// 遍历
	for (i = 0; i < LinkList_Length(list); i++) {
		Teacher* tmp = (Teacher *)LinkList_Get(list, i);
		if (tmp == NULL) {
			return;
		}
		printf("tmp->age:%d\n", tmp->age);
	}

	printf("删除链表\n");
	// 删除链表
	while (LinkList_Length(list) > 0) {
		Teacher* tmp = LinkList_Delete(list, 0);
		if (tmp == NULL) {
			return;
		}
		printf("tmp->age:%d\n", tmp->age);
	}

	LinkList_Destory(list);
}

结果

tmp->age:25
tmp->age:24
tmp->age:23
tmp->age:22
tmp->age:21
删除链表
tmp->age:25
tmp->age:24
tmp->age:23
tmp->age:22
tmp->age:21

2 循环链表

CircleList.h

#ifndef _CIRCLE_LIST_H
#define _CIRCLE_LIST_H

//自定义循环链表数据类型
typedef void CircleList;
//自定义循环链表节点数据类型
typedef struct tag_CirclListNode
{
	struct tag_CirclListNode *next;
}CircleListNode;

//创建结构体管理链表
typedef struct tag_CircleList
{
	//循环链表头结点
	CircleListNode	header;
	//循环链表游标
	CircleListNode	*slider;
	//循环链表长度
	int				length;
}TCircleList;


//创建循环链表
CircleList* CircleList_Create();

//销毁循环链表
void CircleList_Destroy(CircleList* list);

//清空循环链表
void CircleList_Clear(CircleList* list);

//获取循环链表长度
int CircleList_Length(CircleList* list);

//在循环链表中插入新节点
int CircleList_Insert(CircleList* list, CircleListNode* node, int pos);

//获取循环链表中的指定位置的节点
CircleListNode* CircleList_Get(CircleList* list, int pos);

//删除循环链表中的指定位置的节点
CircleListNode* CircleList_Delete(CircleList* list, int pos);

//------------------ new add ------------------

//直接指定删除链表中的某个数据元素
CircleListNode* CircleList_DeleteNode(CircleList* list, CircleListNode* node);

//将游标重置指向链表中的第一个数据元素
CircleListNode* CircleList_Reset(CircleList* list);

//获取当前游标指向的数据元素
CircleListNode* CircleList_Current(CircleList* list);

//将游标移动指向到链表中的下一个数据元素
CircleListNode* CircleList_Next(CircleList* list);

#endif //_CIRCLE_LIST_H

CircleList.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "CircleList.h"


//创建循环链表
CircleList* CircleList_Create()
{
	//定义TCircleList指针变量,并分配内存空间
	TCircleList* tlist = (TCircleList*)malloc(sizeof(TCircleList));
	if (tlist == NULL)
	{
		printf("error: TCircleList* tlist = (TCircleList*)malloc(sizeof(TCircleList)) \n");
		return NULL;
	}
	//数据初始化
	tlist->header.next = NULL;
	tlist->slider = NULL;
	tlist->length = 0;

	return (CircleList*)tlist;
}

//销毁循环链表
void CircleList_Destroy(CircleList* list)
{
	//定义TCircleList指针变量
	TCircleList *tlist = NULL;
	//判断list是否为有效指针
	if (list == NULL)
	{
		printf("Destory error: list 为无效指针\n");
		return;
	}
	free(list);
}


//清空循环链表
void CircleList_Clear(CircleList* list)
{
	//定义TCircleList指针变量
	TCircleList *tlist = NULL;
	//判断list是否为有效指针
	if (list == NULL)
	{
		printf("Clear error: list 为无效指针\n");
		return;
	}
	//类型转换并赋值
	tlist = (TCircleList*)list;
	//将长度重置为0
	tlist->length = 0;
	//头结点指针域指向空
	tlist->header.next = NULL;
	//游标指向空
	tlist->slider = NULL;
}


//获取循环链表长度
int CircleList_Length(CircleList* list)
{
	//定义TCircleList指针变量
	TCircleList *tlist = NULL;
	//判断list是否为有效指针
	if (list == NULL)
	{
		printf("Length error: list 为无效指针\n");
		return -1;
	}
	//类型转换并赋值
	tlist = (TCircleList*)list;

	return tlist->length;
}


//在循环链表中插入新节点
int CircleList_Insert(CircleList* list, CircleListNode* node, int pos)
{
	int i;
	//定义TCircleList指针变量
	TCircleList		*tlist = NULL;
	//定义辅助指针变量
	CircleListNode	*currentNode = NULL;
	//判断list是否为有效指针
	if (list == NULL || node == NULL || pos < 0)
	{
		printf("Insert error: if (list == NULL || node == NULL || pos < 0)\n");
		return -1;
	}
	//类型转换并赋值
	tlist = (TCircleList*)list;

	//元素插入
	//step 1: 使用辅助指针变量,指向头结点
	currentNode = &tlist->header;
	//step 2: 找到pos-1位置节点
	for (i = 0; i < pos; ++i)
	{
		//判断是否有后继节点
		if (currentNode->next != NULL)
		{
			//指针后移
			currentNode = currentNode->next;
		}
		else
		{
			//没有后继节点跳出循环
			break;
		}
	}
	//step 3: 将node节点的指针指向当前节点(pos-1)的后继节点(pos)
	node->next = currentNode->next;
	//step 4: 当前节点的指针指向node节点的地址
	currentNode->next = node;
	//step 5: 如果是第一次插入节点
	if (tlist->length == 0)
	{
		//将游标指向新插入节点
		tlist->slider = node;
	}
	//step 6: 链表长度加1
	tlist->length++;
	//step 7:若头插法 currentNode仍然指向头部
	//原因: 跳0步, 没有跳走
	if (currentNode == &tlist->header)
	{
		CircleListNode* lastNode = CircleList_Get(list, tlist->length - 1);
		//最后一个节点的指针,指向第一个数据节点
		lastNode->next = currentNode->next;
	}
	return 0;
}


//获取循环链表中的指定位置的节点
CircleListNode* CircleList_Get(CircleList* list, int pos)
{
	int				i;
	//定义TCircleList指针变量
	TCircleList		*tlist = NULL;
	//定义辅助指针变量
	CircleListNode	*currentNode = NULL;
	//判断list是否为有效指针
	if (list == NULL || pos < 0)
	{
		printf("CircleList_Get error: if (list == NULL || pos < 0)\n");
		return NULL;
	}
	//类型转换并赋值
	tlist = (TCircleList*)list;

	//step 1: 使用辅助指针变量,指向头结点
	currentNode = &tlist->header;
	//step 2: 找到pos位置节点
	for (i = 0; i <= pos; ++i)
	{
		//判断是否有后继节点
		if (currentNode->next != NULL)
		{
			//指针后移
			currentNode = currentNode->next;
		}
		else
		{
			//没有后继节点跳出循环
			printf("error: 没找到指定位置的元素\n");
			return NULL;
		}
	}

	return currentNode;
}


//删除循环链表中的指定位置的节点
//-------------------------------
CircleListNode* CircleList_Delete(CircleList* list, int pos)
{
	int				i;
	//定义TCircleList指针变量
	TCircleList		*tlist = NULL;
	//定义链表节点指针,保存要删除的节点地址
	CircleListNode	*deleteNode = NULL;
	//定义链表节点指针,保存最后一个节点
	CircleListNode  *lastNode = NULL;
	//定义辅助指针变量
	CircleListNode  *currentNode = NULL;


	//判断list是否为有效指针
	if (list == NULL || pos < 0)
	{
		printf("CircleList_Delete error: if (list == NULL || pos < 0)\n");
		return NULL;
	}
	//类型转换并赋值
    // tlist = (TCircleList*)list->header; // list 和 list->header的地址重叠
	tlist = (TCircleList*)list;
	//判断链表中是否有节点
	if (tlist->length <= 0)
	{
		printf("error: 链表为空,不能删除\n");
		return NULL;
	}

	//元素删除
	//step 1: 辅助指针变量,指向头结点
	currentNode = &tlist->header;
	//step 2: 找到pos-1位置节点
	for (i = 0; i < pos; ++i)
	{
		//指针后移
		currentNode = currentNode->next;
	}
	//step 3: 保存要删除的节点的地址
	deleteNode = currentNode->next;
	//step 4-1: 判断删除的元素是否为第一个元素
	if (currentNode == &tlist->header)
	{
		//step 4-2: 找到最后一个节点
		lastNode = CircleList_Get(list, tlist->length - 1);
	}
	//step 4-3: 判断lastNode是否为空
	if (lastNode != NULL)
	{
		//step 4-4: 将最后一个节点的地址指向要删除节点的后继节点
		lastNode->next = deleteNode->next;
	}
	//step 4-5: 将头结点的指针指向要删除节点的后继节点
	currentNode->next = deleteNode->next;
	//step 5: 链表长度减1
	tlist->length--;
	//step 6-1: 判断删除的元素是否为游标指向的元素
	if (tlist->slider == deleteNode)
	{
		//step 6-2: 游标后移
		tlist->slider = deleteNode->next;
	}
	//step 7-1: 判断删除元素后,链表长度是否为零
	if (tlist->length == 0)
	{
		//step 7-2: 链表头结点指针域指向空
		tlist->header.next = NULL;
		//step 7-3: 链表游标指向空
		tlist->slider = NULL;
	}

	return deleteNode;
}


//------------------ new add ------------------

//直接指定删除链表中的某个数据元素
CircleListNode* CircleList_DeleteNode(CircleList* list, CircleListNode* node)
{
	int			i;
	int			nPos = 0;
	//定义TCircleList指针变量
	TCircleList *tlist = NULL;
	//判断list是否为有效指针
	if (list == NULL || node == NULL)
	{
		printf("CircleList_DeleteNode error: if (list == NULL || node == NULL)\n");
		return NULL;
	}
	//类型转换并赋值
	tlist = (TCircleList*)list;

	//定义辅助指针变量,指向头结点
	CircleListNode* currentNode = &tlist->header;
	//定义辅助指针变量,用来保存要删除的节点地址
	CircleListNode* delNode = NULL;
	//查找node节点在循环链表中的位置
	for (i = 0; i < tlist->length; ++i)
	{
		//从第一个数据节点开始判断,查找等于node的节点
		if (currentNode->next == node)
		{
			//保存与node节点相等的节点的位置
			nPos = i;
			//保存要删除的节点地址
			delNode = currentNode->next;
			//跳出循环
			break;
		}
		//当前节点指针后移
		currentNode = currentNode->next;
	}
	//如果找到delNode,根据nPos删除该节点
	if (delNode != NULL)
	{
		//删除指定位置的元素
		CircleList_Delete(list, nPos);
	}

	return delNode;
}


//将游标重置指向链表中的第一个数据元素
CircleListNode* CircleList_Reset(CircleList* list)
{
	//定义TCircleList指针变量
	TCircleList *tlist = NULL;
	//判断list是否为有效指针
	if (list == NULL)
	{
		printf("CircleList_Reset error: if (list == NULL)\n");
		return NULL;
	}
	//类型转换并赋值
	tlist = (TCircleList*)list;
	//重置游标位置
	tlist->slider = tlist->header.next;

	return tlist->slider;
}


//获取当前游标指向的数据元素
CircleListNode* CircleList_Current(CircleList* list)
{
	//定义TCircleList指针变量
	TCircleList *tlist = NULL;
	//判断list是否为有效指针
	if (list == NULL)
	{
		printf("CircleList_Current error: if (list == NULL)\n");
		return NULL;
	}
	//类型转换并赋值
	tlist = (TCircleList*)list;

	return tlist->slider;
}


//将游标移动指向到链表中的下一个数据元素
CircleListNode* CircleList_Next(CircleList* list)
{
	//定义链表节点指针变量
	CircleListNode	*currNode = NULL;
	//定义TCircleList指针变量
	TCircleList		*tlist = NULL;
	//判断list是否为有效指针
	if (list == NULL)
	{
		printf("CircleList_Next error: if (list == NULL)\n");
		return NULL;
	}
	//类型转换并赋值
	tlist = (TCircleList*)list;
	//存储当前游标位置
	currNode = tlist->slider;

	//判断当前游标是否指向空
	if (tlist->slider != NULL)
	{
		//游标后移
		tlist->slider = currNode->next;
	}

	return currNode;
}

demo01_循环链表基本功能测试.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "CircleList.h"

typedef struct tag_value
{
	CircleListNode circleNode;
	int v;
}Value;

#if 0
int main()
{
	int i;
	//定义Value结构体数组
	Value val[10];	//创建循环链表
	CircleList* list = CircleList_Create();

	//循环初始化数组
	for (i = 0; i < sizeof(val) / sizeof(Value); ++i)
	{
		val[i].v = i + 20;
		//往循环链表中插入数据
		CircleList_Insert(list, (CircleListNode*)&val[i], i);
	}
	//遍历循环链表
	//************* 怎么证明是循环链表? *************
	for (i = 0; i < CircleList_Length(list) * 2; ++i)	//打印两遍
	{
		Value *pVal = (Value*)CircleList_Get(list, i);
		printf("Value %d = %d\n", i, pVal->v);
	}
	//删除节点
	while (CircleList_Length(list) > 0)
	{
		Value *pVal = (Value*)CircleList_Delete(list, 0);
		printf("Delete Value: val = %d\n", pVal->v);
	}
	//销毁循环链表
	CircleList_Destroy(list);

	return 0;
}
#endif

结果

Value 0 = 20
Value 1 = 21
Value 2 = 22
Value 3 = 23
Value 4 = 24
Value 5 = 25
Value 6 = 26
Value 7 = 27
Value 8 = 28
Value 9 = 29
Value 10 = 20
Value 11 = 21
Value 12 = 22
Value 13 = 23
Value 14 = 24
Value 15 = 25
Value 16 = 26
Value 17 = 27
Value 18 = 28
Value 19 = 29
Delete Value: val = 20
Delete Value: val = 21
Delete Value: val = 22
Delete Value: val = 23
Delete Value: val = 24
Delete Value: val = 25
Delete Value: val = 26
Delete Value: val = 27
Delete Value: val = 28
Delete Value: val = 29

demo02_约瑟夫问题求解.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "circlelist.h"

/*
	约瑟夫问题-循环链表典型应用
	n 个人围成一个圆圈,首先第 1 个人从 1 开始一个人一个人顺时针报数,
	报到第 m 个人,令其出列。然后再从下一 个人开始从 1 顺时针报数,报
	到第 m 个人,再令其出列,…,如此下去,求出列顺序。

	求解: 假设 m = 3, n = 8 (1 2 3 4 5 6 7 8)
	结果: 3 6 1 5 2 8 4 7
*/


#if 0
//定义结构体,存储数据
typedef struct tag_value
{
	CircleListNode header;
	int v;
}Value;

void joseph_question()
{
	int i;
	//定义结构体数组
	Value val[8];
	//创建循环链表
	CircleList* list = CircleList_Create();
	//判断链表是否创建成功
	if (list == NULL)
	{
		printf("链表创建失败\n");
		return;
	}
	//初始化结构体数组
	for (i = 0; i < sizeof(val) / sizeof(Value); ++i)
	{
		val[i].v = i+1;
		//往循环链表中插入数据
		CircleList_Insert(list, (CircleListNode*)&val[i], i);
	}
	//遍历循环链表
	printf("插入数据:\n");
	for (i = 0; i < CircleList_Length(list); ++i)
	{
		//获取游标指向的元素然后下移
		Value* pVal = (Value*)CircleList_Get(list, i);
		printf("%d\t", pVal->v);
	}

	//重置游标
	CircleList_Reset(list);
	//循环删除指定位置的元素
	printf("\n\n依次删除的节点为:\n");
	while (CircleList_Length(list) > 0)
	{
		//定义结构体指针变量,指向符合条件的元素
		Value* pVal = NULL;
		//根据条件查找指定位置的元素
		for (i = 0; i < 3-1; ++i)	//3为案例中的m
		{
			//向后移动游标
			pVal = (Value*)CircleList_Next(list);
		}
		//保存符合条件的节点
		pVal = (Value*)CircleList_Current(list);
		//打印节点信息
		printf("%d\t", pVal->v);
		//从链表中删除符合条件的节点
		CircleList_DeleteNode(list, (CircleListNode*)pVal);
	}
	printf("\n");
	//销毁循环链表
	CircleList_Destroy(list);
}

#else
// 定义数据结构
// 业务节点的定义
typedef struct _Value
{
	// 内部的链表节点
	CircleListNode node;
	int v;	// 数据
}Value;


void joseph_question()
{
	Value val[8];
	// 创建循环链表
	CircleList *list = CircleList_Create();
	// 初始化数组
	for (int i = 0; i < 8; ++i)
	{
		val[i].v = i + 1;
		// 节点插入到链表
		CircleList_Insert(list, &val[i].node, i);
		//CircleList_Insert(list, (CircleListNode*)&val[i], i);
	}
	// 遍历
	for (int i = 0; i < CircleList_Length(list); ++i)
	{
		Value* p = (Value*)CircleList_Get(list, i);
		printf("%d  ", p->v);
	}
	printf("\n");

	// 出链表操作
	// 游标重置, 指向第一个数据节点
	printf("删除的节点的次序\n");
	CircleList_Reset(list);
	while (CircleList_Length(list))
	{
		// 游标后移的步长
		for (int i = 0; i < 2; ++i)
		{
			// 游标后移
			CircleList_Next(list);
		}
		// 获取当前游标指向的节点
		Value* p = (Value*)CircleList_Current(list);
		// 
		printf("%d  ", p->v);
		// 删除当前节点
		CircleList_DeleteNode(list, (CircleListNode*)p);
	}
	CircleList_Destroy(list);

}

#endif

#if 1
void main()
{
	joseph_question();
	system("pause");
}
#endif

结果

1  2  3  4  5  6  7  8
删除的节点的次序
3  6  1  5  2  8  4  7

3 双向链表

DLinkList.h

#ifndef _DLINK_LIST_H
#define _DLINK_LIST_H

//自定义双向链表数据类型
typedef void DLinkList;
//自定义双向链表节点数据类型
typedef struct tag_dLinkListNode
{
	struct tag_dLinkListNode *prev;
	struct tag_dLinkListNode *next;
}DLinkListNode;

//定义管理双向链表的结构体
typedef struct _tag_dlinklist
{
	DLinkListNode head;
	DLinkListNode *slider;
	int length;
}TDLinkList;
 
//创建链表
DLinkList* DLinkList_Create();

//销毁链表
void DLinkList_Destroy(DLinkList* list);

//清空链表
void DLinkList_Clear(DLinkList* list);

//获取链表长度
int DLinkList_Length(DLinkList* list);

//获取第pos个元素操作
DLinkListNode* DLinkList_Get(DLinkList* list, int pos);

//插入元素到位置pos
int DLinkList_Insert(DLinkList* list, DLinkListNode* node, int pos);

//删除位置pos处的元素
DLinkListNode* DLinkList_Delete(DLinkList* list, int pos);

//获取当前游标指向的数据元素
DLinkListNode* DLinkList_Current(DLinkList* list);

//将游标重置指向链表中的第一个数据元素
DLinkListNode* DLinkList_Reset(DLinkList* list);

//将游标移动指向到链表中的下一个数据元素
DLinkListNode* DLinkList_Next(DLinkList* list);

//将游标移动指向到链表中的上一个数据元素
DLinkListNode* DLinkList_Prev(DLinkList* list);

//直接指定删除链表中的某个数据元素
DLinkListNode* DLinkList_DeleteNode(DLinkList* list, DLinkListNode* node);

#endif //_DLINK_LIST_H

DLinkList.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "DLinkList.h"



//创建链表
DLinkList* DLinkList_Create()
{
	//定义结构体类型指针变量,并分配内存空间
	TDLinkList* dlist = (TDLinkList*)malloc(sizeof(TDLinkList));
	//如果分配内存成功,则初始化变量
	if (dlist != NULL)
	{
		dlist->head.next = NULL;
		dlist->slider = NULL;
		dlist->length = 0;
		return (DLinkList*)dlist;
	}
	//失败返回空
	printf("分配内存失败\n");
	return NULL;
}

//销毁链表
void DLinkList_Destroy(DLinkList* list)
{
	//判断list是否为有效指针
	if (list != NULL)
	{
		//释放内存空间
		free(list);
	}
}

//清空链表
void DLinkList_Clear(DLinkList* list)
{
	//判断list是否为有效指针
	if (list != NULL)
	{
		//定义结构体类型指针,并给其赋值
		TDLinkList* dlist = (TDLinkList*)list;
		//数据重置
		dlist->length = 0;
		dlist->head.next = NULL;
		dlist->slider = NULL;
	}
}

//获取链表长度
int DLinkList_Length(DLinkList* list)
{
	//判断list是否为有效指针
	if (list != NULL)
	{
		//定义结构体类型指针,并给其赋值
		TDLinkList* dlist = (TDLinkList*)list;
		return dlist->length;
	}
	printf("DLinkList_Length error: list 指针无效\n");
	return -1;
}

//获取第pos个元素操作
DLinkListNode* DLinkList_Get(DLinkList* list, int pos)
{
	//判断list是否为有效指针
	if (list != NULL)
	{
		//定义结构体类型指针,并给其赋值
		TDLinkList* dlist = (TDLinkList*)list;
		//定义辅助指针变量, 并初始化,指向头节点
		DLinkListNode* currNode = &dlist->head;
		//循环查找pos位置元素
		for (int i = 0; i <= pos; ++i)
		{
			currNode = currNode->next;
		}
		return currNode;
	}

	printf("DLinkList_Get error: list 指针无效\n");
	return NULL;
}

//插入元素到位置pos
int DLinkList_Insert(DLinkList* list, DLinkListNode* node, int pos)
{
	//判断list是否为有效指针
	if (list != NULL)
	{
		//定义结构体类型指针,并给其赋值
		TDLinkList* dlist = (TDLinkList*)list;
		//定义辅助指针变量, 并初始化,指向头节点
		DLinkListNode* currNode = &dlist->head;
		//定义辅助指针变量
		DLinkListNode* posNode = NULL;
		//循环查找pos-1位置元素
		for (int i = 0; i < pos; ++i)
		{
			//判断是否有后继节点
			if (currNode->next != NULL)
			{
				//指针后移
				currNode = currNode->next;
			}
			else
			{
				//没有后继节点,结束循环
				break;
			}
		}
		//赋值,辅助指针变量指向pos位置节点
		posNode = currNode->next;

		//开始插入元素
		//step1: 将新节点的next域指针指向pos位置节点的地址
		node->next = posNode;
		//step2: 将当前节点的next域指针指向新插入节点的地址
		currNode->next = node;
		//step3: 将pos位置的节点的prev域指针指向新插入节点的地址
		//********** 特殊处理 **********
		if (posNode != NULL)	//当链表插入第一个元素需要特殊处理
		{
			posNode->prev = node;
		}
		//step4: 将新插入节点的地址指向当前节点的地址
		node->prev = currNode;
		//********** 特殊处理 **********
		if (currNode == &dlist->head)	//如果链表为空
		{
			//将第一个节点的前驱节点设为空
			node->prev = NULL;
			//游标指向第一个节点
			dlist->slider = node;
		}
		//step4: 链表长度加1
		dlist->length++;

		return 0;
	}

	printf("DLinkList_Insert error: list 指针无效\n");
	return -1;
}

//删除位置pos处的元素
DLinkListNode* DLinkList_Delete(DLinkList* list, int pos)
{
	//判断list是否为有效指针
	if (list != NULL && pos >= 0)
	{
		//定义结构体类型指针,并给其赋值
		TDLinkList* dlist = (TDLinkList*)list;
		//定义辅助指针变量, 并初始化,指向头节点
		DLinkListNode* currNode = &dlist->head;
		//定义辅助指针变量
		DLinkListNode* delNode = NULL;
		DLinkListNode* nextNode = NULL;
		//循环查找pos-1位置元素
		for (int i = 0; i < pos; ++i)
		{
			currNode = currNode->next;
		}
		//赋值
		delNode = currNode->next;
		nextNode = delNode->next;

		//开始删除元素
		//step1: 将当前节点的next域指针指向被删除节点的后继节点
		currNode->next = nextNode;
		//****** 需要特殊处理 ******
		if (nextNode != NULL)
		{
			//step2: nextNode节点的prev域指针指向当前节点的地址
			nextNode->prev = currNode;
			//****** 需要特殊处理 ******
			if (currNode == &dlist->head)	//如果当前节点为头结点
			{
				//将nextNode节点指向空
				nextNode->prev = NULL;
			}
		}
		//step 3: 链表长度减1
		dlist->length--;

		//判断删除的元素是不是当前游标指向的位置
		if (dlist->slider == delNode)
		{
			//如果是,游标后移
			dlist->slider = nextNode;
		}

		return delNode;
	}

	printf("DLinkList_Delete error: list指针 或 pos位置无效\n");
	return NULL;
}

//获取当前游标指向的数据元素
DLinkListNode* DLinkList_Current(DLinkList* list)
{
	//判断list是否为有效指针
	if (list != NULL)
	{
		//定义结构体类型指针,并给其赋值
		TDLinkList* dlist = (TDLinkList*)list;
		return dlist->slider;
	}

	printf("DLinkList_Current error: list 指针无效\n");
	return NULL;
}

//将游标重置指向链表中的第一个数据元素
DLinkListNode* DLinkList_Reset(DLinkList* list)
{
	//判断list是否为有效指针
	if (list != NULL)
	{
		//定义结构体类型指针,并给其赋值
		TDLinkList* dlist = (TDLinkList*)list;
		dlist->slider = dlist->head.next;
		return dlist->slider;
	}

	printf("DLinkList_Reset error: list 指针无效\n");
	return NULL;
}

//将游标移动指向到链表中的下一个数据元素
DLinkListNode* DLinkList_Next(DLinkList* list)
{
	//判断list是否为有效指针
	if (list != NULL)
	{
		//定义结构体类型指针,并给其赋值
		TDLinkList* dlist = (TDLinkList*)list;
		//定义链表节点指针保存当前游标地址
		DLinkListNode* currSlider = dlist->slider;
		//游标后移
		if (dlist->slider->next != NULL)
		{
			dlist->slider = dlist->slider->next;
			return currSlider;
		}
		else
		{
			return NULL;
		}
	}

	printf("DLinkList_Next error: list 指针无效\n");
	return NULL;
}

//将游标移动指向到链表中的上一个数据元素
DLinkListNode* DLinkList_Prev(DLinkList* list)
{
	//判断list是否为有效指针
	if (list != NULL)
	{
		//定义结构体类型指针,并给其赋值
		TDLinkList* dlist = (TDLinkList*)list;
		//定义链表节点指针保存当前游标地址
		DLinkListNode* currSlider = dlist->slider;
		//游标前移
		dlist->slider = dlist->slider->prev;
		return currSlider;
	}

	printf("DLinkList_Prev error: list 指针无效\n");
	return NULL;
}

//直接指定删除链表中的某个数据元素
DLinkListNode* DLinkList_DeleteNode(DLinkList* list, DLinkListNode* node)
{
	//判断list是否为有效指针
	if (list != NULL)
	{
		int nPos = 0;
		//定义结构体类型指针,并给其赋值
		TDLinkList* dlist = (TDLinkList*)list;
		//查找与node节点相等的节点
		for (int i = 0; i < dlist->length; ++i)
		{
			if (node == DLinkList_Get(list, i))
			{
				//保存位置
				nPos = i;
				//跳出循环
				break;
			}
		}
		//删除指定nPos位置节点
		DLinkListNode* delNode = DLinkList_Delete(list, nPos);
		return delNode;
	}

	printf("DLinkList_DeleteNode error: list or node 指针无效\n");
	return NULL;
}

双向链表基本功能测试.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "DLinkList.h"

//定义数据结构体
typedef struct tag_value
{
	//包含双向链表的一个节点
	DLinkListNode head;
	int value;
}Value;

//双向链表测试程序
void dLinkListTest()
{
	int i;
	//定义结构体数组
	Value val[10];
	//创建双向链表
	DLinkList *dlist = DLinkList_Create();
	//判断是否创建成功
	if (dlist == NULL)
	{
		printf("双向链表创建失败\n");
		return;
	}
	//初始化并向链表中插入数据
	for (i = 0; i < sizeof(val) / sizeof(Value); ++i)
	{
		val[i].value = i + 10;
		//向尾部插入元素
		DLinkList_Insert(dlist, (DLinkListNode*)&val[i], i);
	}
	//遍历双向链表
	printf("遍历双向链表\n");
	for (int i = 0; i < DLinkList_Length(dlist); ++i)
	{
		//获取指定位置元素
		Value* val = (Value*)DLinkList_Get(dlist, i);
		printf("%d\t", val->value);
	}
	printf("\n");

	//删除最后一个节点
	DLinkList_Delete(dlist, DLinkList_Length(dlist) - 1);
	//删除第一节点
	DLinkList_Delete(dlist, 0);
	//再次遍历链表
	printf("再次遍历双向链表\n");
	for (int i = 0; i < DLinkList_Length(dlist); ++i)
	{
		//获取指定位置元素
		Value* val = (Value*)DLinkList_Get(dlist, i);
		printf("%d\t", val->value);
	}
	printf("\n");

	//重置游标
	DLinkList_Reset(dlist);
	//游标后移
	DLinkList_Next(dlist);
	//获取当前游标指向的节点
	Value* pVal = (Value*)DLinkList_Current(dlist);
	//打印当前节点的value值
	printf("DLinkList_Next --- 打印当前节点的value值: value = %d\n", pVal->value);
	//删除游标指向的当前节点
	DLinkList_DeleteNode(dlist, (DLinkListNode*)pVal);
	//再次获取当前游标指向的节点
	pVal = (Value*)DLinkList_Current(dlist);
	//再次打印当前节点的value值
	printf("DLinklist_DeleteNode --- 再次打印当前节点的value值: value = %d\n", pVal->value);

	//向前移动游标
	DLinkList_Prev(dlist);
	//第三次获取当前游标指向的节点
	pVal = (Value*)DLinkList_Current(dlist);
	//第三次打印当前节点的value值
	printf("DLinkList_Prev --- 再次打印当前节点的value值: value = %d\n", pVal->value);

	//打印链表的长度
	printf("打印链表的长度, Length = %d\n", DLinkList_Length(dlist));

	//销毁双向链表
	DLinkList_Destroy(dlist);
}

void main()
{
	dLinkListTest();
	system("pause");
}

结果

遍历双向链表
10      11      12      13      14      15      16      17      18      19
再次遍历双向链表
11      12      13      14      15      16      17      18
DLinkList_Next --- 打印当前节点的value值: value = 12
DLinklist_DeleteNode --- 再次打印当前节点的value值: value = 13
DLinkList_Prev --- 再次打印当前节点的value值: value = 11
打印链表的长度, Length = 7
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值