0
点赞
收藏
分享

微信扫一扫

机器学习基础-数据分析:房价预测

目录

链表的分类

带头双向循环链表的实现

带头双向循环链表的结构

带头双向循环链表的结构示意图

空链表结构示意图

单结点链表结构示意图

 多结点链表结构示意图

链表创建结点

双向链表初始化

销毁双向链表

打印双向链表

 双向链表尾插

尾插函数测试

双向链表头插

头插函数测试

 双向链表尾删

尾删函数测试

双向链表头删

头删函数测试

双向链表查找

双向链表pos位置前插

插入函数测试

 双向链表删除pos位置的结点

删除函数测试

利用 ListInsert()函数改造头插尾插函数

尾插函数改造版本

头插函数改造版本

利用ListEarse()函数改造头删 尾删函数

头删函数改造版本

尾删函数改造版本

计算双向链表长度


链表的分类

  • 单向/双向

 

  • 带头/不带头

 

  • 循环/非循环

带头双向循环链表的实现

带头双向循环链表的结构

typedef int LTDataType;
typedef struct ListNode
{
	struct ListNode* prev;//前址域-存放前一个结点的地址
	LTDataType data;//数据域
	struct ListNode* next;//后址域-存放后一个结点的地址
}ListNode;

逻辑图:

物理图:

带头双向循环链表的结构示意图

  • 空链表结构示意图

  • 单结点链表结构示意图

  •  多结点链表结构示意图

链表创建结点

//创建链表结点,返回链表结点地址
ListNode* BuyListNode(LTDataType x)
{
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	if (newnode == NULL)
	{
		perror("malloc failed:");
		exit(-1);
	}

	newnode->data = x;
	newnode->next = NULL;
	newnode->prev = NULL;

	return newnode;
}

双向链表初始化

//初始化链表(空链表)
ListNode* ListInit()
{
	//创建哨兵位结点
	ListNode* head = BuyListNode(0);//0不是有效数据

	//初始化哨兵位结点的指针域
	head->next = head;
	head->prev = head;

	return head;
}

销毁双向链表

//销毁链表,包含哨兵位结点
void DestoryList(ListNode* phead)
{
	assert(phead);

	//创建寻址指针
	ListNode* cur = phead;
	//断开循环链表
	phead->prev->next = NULL;
	while (cur != NULL)
	{
		//记录下一结点地址
		ListNode* next = cur->next;
        //释放当前结点
		free(cur);
		//寻找下一节点
		cur = next;
	}
	return;
}

打印双向链表

void PrintList(ListNode* phead)
{
	assert(phead != NULL);

	ListNode* cur = phead->next;

	printf("phead<==>");
	while (cur != phead)
	{
		printf("%d<==>", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

 双向链表尾插

void ListPushBack(ListNode* phead, LTDataType x)
{
	assert(phead);
    
	//寻找尾结点
	ListNode* tail = phead->prev;
    //创建新结点
	ListNode* newnode = BuyListNode(x);

   //尾插
	newnode->prev = tail;
	tail->next = newnode;

	newnode->next = phead;
	phead->prev = newnode;
}
尾插函数测试
void Test1()
{
	ListNode* plist=ListInit();
	
	ListPushBack(plist, 1);
	ListPushBack(plist, 2);
	ListPushBack(plist, 3);
	ListPushBack(plist, 4);
	ListPushBack(plist, 5);
	PrintList(plist);
}
int main()
{
	Test1();
	return 0;
}

运行结果:

双向链表头插

//链表头插
void ListPushFront(ListNode* phead, LTDataType x)
{
	assert(phead);

	//保存原先的首节点
	ListNode* firstnode = phead->next;
	//创建新结点
	ListNode* newnode = BuyListNode(x);

	//头插
	newnode->prev = phead;
	phead->next = newnode;

	newnode->next = firstnode;
	firstnode->prev = newnode;
}
头插函数测试
void Test2()
{
	ListNode* plist = ListInit();
	ListPushFront(plist, 10);
	ListPushFront(plist, 20);
	ListPushFront(plist, 30);
	ListPushFront(plist, 40);
	ListPushFront(plist, 50);
	PrintList(plist);

}
int main()
{
	Test2();
	return 0;
}

运行结果:

 双向链表尾删

//链表尾删
void ListPopBack(ListNode* phead)
{
	assert(phead);

	//链表中只剩哨兵位的情况
	assert(phead->next != phead);

	//查找尾结点
	ListNode* tail = phead->prev;
	//保存尾结点的上一节点
	ListNode* tailprev = tail->prev;

   //尾删
	free(tail);
   //建立链接关系
	tailprev->next = phead;
	phead->prev = tailprev;

}
尾删函数测试
void Test3()
{
	ListNode* plist = ListInit();

	ListPushBack(plist, 1);
	ListPushBack(plist, 2);
	ListPushBack(plist, 3);
	ListPushBack(plist, 4);
	ListPushBack(plist, 5);
	PrintList(plist);

	ListPopBack(plist);
	PrintList(plist);

	ListPopBack(plist);
	PrintList(plist);

	ListPopBack(plist);
	PrintList(plist);

}
int main()
{
	Test3();
	return 0;
}

运行结果:

双向链表头删

//链表头删
void ListPopFront(ListNode* phead)
{
	assert(phead);
	//只剩哨兵位,不再头删
	assert(phead->next != phead);

	//保存原先的首节点
	ListNode* head = phead->next;

	//保存首结点的下一节点
	ListNode* headnext = phead->next->next;

	//头删
	free(head);
	//建立链接关系
	headnext->prev = phead;
	phead->next = headnext;

}
头删函数测试
void Test4()
{
	ListNode* plist = ListInit();

	ListPushBack(plist, 1);
	ListPushBack(plist, 2);
	ListPushBack(plist, 3);
	ListPushBack(plist, 4);
	ListPushBack(plist, 5);
	PrintList(plist);

	ListPopFront(plist);
	PrintList(plist);

	ListPopFront(plist);
	PrintList(plist);

	ListPopFront(plist);
	PrintList(plist);
}
int main()
{
	Test4();
	return 0;
}

运行结果:

双向链表查找

ListNode* ListFind(ListNode* phead, LTDataType x)
{
	assert(phead);

	//创建遍历指针
	ListNode* cur = phead->next;

	//遍历链表
	while (cur != phead)
	{
		if ((cur->data) == x)
		{
			//找到返回下标
			return cur;
		}
		cur = cur->next;
	}
	//没找到返回空指针
	return NULL;
}

双向链表pos位置前插

void ListInsert(ListNode* pos, LTDataType x)
{
	assert(pos != NULL);

	//创建新结点
	ListNode* newnode = BuyListNode(x);
	//保存pos位置的前一个结点
	ListNode* posprev = pos->prev;

	//前插
	newnode->prev = posprev;
	posprev->next = newnode;
	newnode->next = pos;
	pos->prev = newnode;
}
插入函数测试
void Test5()
{
	ListNode* plist = ListInit();
	ListPushBack(plist, 1);
	ListPushBack(plist, 2);
	ListPushBack(plist, 3);
	ListPushBack(plist, 4);
	ListPushBack(plist, 5);

	int x = 0;
	printf("请输入查找的数值:");
	scanf("%d", &x);
	ListNode* pos = ListFind(plist, x);
	if (pos == NULL)
	{
		printf("要查找的值不存在\n");
		return;
	}
	//在查找到数值前插入100
	ListInsert(pos, 100);
	PrintList(plist);

}
int main()
{
	Test5();
	return 0;
}

运行结果:

 双向链表删除pos位置的结点

//双向链表删除pos位置
void ListEarse(ListNode* pos)
{
	assert(pos);

	//保存pos位置处的前一个和后一个结点;
	ListNode* posprev = pos->prev;
	ListNode* posnext = pos->next;
	//删除pos位置结点
	free(pos);

	//建立前后节点的链接关系
	posprev->next = posnext;
	posnext->prev = posprev;

}
删除函数测试
void Test6()
{
	ListNode* plist = ListInit();
	ListPushBack(plist, 1);
	ListPushBack(plist, 2);
	ListPushBack(plist, 3);
	ListPushBack(plist, 4);
	ListPushBack(plist, 5);
	PrintList(plist);

	int x = 0;
	printf("请输入删除的数值:");
	scanf("%d", &x);
	ListNode* pos = ListFind(plist, x);
	if (pos == NULL)
	{
		printf("要删除的值不存在\n");
		return;
	}
	
	ListEarse(pos);
	PrintList(plist);
}
int main()
{
	Test6();
	return 0;
}

运行结果:

利用 ListInsert()函数改造头插尾插函数

  • 尾插函数改造版本
void Listpushback(ListNode* phead, LTDataType x)
{
	assert(phead);
	ListInsert(phead, x);
}
  • 头插函数改造版本
void Listpushfront(ListNode* phead, LTDataType x)
{
	assert(phead);
	ListInsert(phead->next, x);
}

利用ListEarse()函数改造头删 尾删函数

  • 头删函数改造版本
void Listpopfront(ListNode* phead)
{
	assert(phead);
	//只剩哨兵位,不再头删
	assert(phead->next != phead);

	ListEarse(phead->next);
}
  • 尾删函数改造版本
void Listpopback(ListNode* phead)
{
	assert(phead);

	//链表中只剩哨兵位的情况
	assert(phead->next != phead);

	ListEarse(phead->prev);
}

计算双向链表长度

int ListLength(ListNode* phead)
{
	assert(phead);

	int size = 0;
	ListNode* cur = phead->next;
	while (cur != phead)
	{
		++size;
		cur = cur->next;
	}
	return size;
}

 

 

 

 

 

 

举报

相关推荐

机器学习中的数据分析

0 条评论