以往博客的复习补充——part1

news2025/1/7 11:59:38

之前没更新是因为期末考试要复习,没空写博客。1月3号才考完,现在有空,打算从头看一遍,既是复习以前知识点,又是对原来的博客进行补充。刚好寒假,有大把时间。

一,希尔排序(Shell Sort)

算是插入排序的改进。因为插入算法相比三傻排序的另外两个,在序列有序时能够节省时间复杂;而且插入排序会在数据量比较小的时候效率比较高。所以通过增量将数组进行分组,开始增量较大,每组数据量较小,很快就能排有序。然后逐渐缩小增量,在分组内进行插入排序。直至增量为1.

还有就是增量是多少,就会分为几个组。因为一个组内两个元素的间隔为增量,中间就会夹着增量个元素,意味着还要分多少组。

希尔排序也叫作缩小增量排序。在排序过程中开始分组多但组内元素少,后来分组少元素多,但是越来越有序的。

具体过程看下面教程或者b站视频《数据结构合集——希尔排序》蓝不过海呀。

六大排序算法:插入排序、希尔排序、选择排序、冒泡排序、堆排序、快速排序-CSDN博客

我写下代码:

第一次写的,只能说是漏洞百出,不忍直视。

#include<stdio.h>

int main()
{
	int arr[] = { 3,2,4,9,6,1,5,7,8 };
	int len = sizeof(arr) / sizeof(int);

	for (int i = 0; i < len; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");

	int gap = len / 2;
	int turn = 2;
	while (turn)
	{
		//当前增量下,会分为几组,也就会进行几轮插入排序。
		for (int i = 0; i < (len / gap); i++)
		{
			int end = i;//end是有序队列末尾。
			int temp = arr[end + gap];//temp临时变量代表将要插入的元素。
			//接下来就是组内进行插入排序。
			while (end >= 0)
			{
				if (arr[end] > temp)
				{
					arr[end + gap] = arr[end];//大于插入元素的往后移,它的位置空出来了。
					end -= gap;
				}
				else break;
			}

			arr[end + gap] = temp;
		}

		//接下来更新增量,进行下一轮排序。
		gap /= 2;
		if (gap == 1) turn--;//第一次gap等于1时循环不会结束。
	}
	printf("end");

	for (int i = 0; i < len; i++)
	{
		printf("%d ", arr[i]);
	}

	return 0;
}

这是AI分析出的问题:
 

问题 1:分组逻辑有误

在 for (int i = 0; i < (len / gap); i++) 这一部分,你的分组逻辑错误。希尔排序的核心思想是在当前增量 gap 下,对所有以 gap 为间隔的元素分组,然后对每组进行插入排序。这里你按 (len / gap) 的方式分组,但实际上应该从每个分组的起始点出发进行分组,即从 0 到 gap - 1 的每个起点出发。


问题 2:组内插入排序逻辑有误

int end = i;  // end 是有序队列的末尾
int temp = arr[end + gap];

这里 end 设置为 i 是不正确的,因为在希尔排序中,组内的有序序列需要从当前分组起点逐步扩展,而不是简单地以分组的索引作为 end

正确的逻辑是从当前分组的起始点出发,按增量 gap 逐步移动进行插入排序。


问题 3:增量更新逻辑有误

你的增量更新逻辑是:

gap /= 2;
if (gap == 1) turn--;

这里你设置了一个变量 turn,试图在 gap == 1 时多循环一次。但这是不必要的,希尔排序的结束条件应当是 gap == 0,即在最后一次增量为 1 的插入排序完成后结束。

这是我自己改的代码

#include<stdio.h>

int main()
{
	int arr[] = { 3,2,4,9,6,1,5,7,8 };
	int len = sizeof(arr) / sizeof(int);

	for (int i = 0; i < len; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");

	int gap = len / 2;
	while (gap)
	{
		//当前增量下,会分为几组,也就会进行几轮插入排序。
		for (int i = 0; i < gap; i++)
		{
			int end = i;//end是有序队列末尾。从开始序号为i这组进行插入排序。
			while (end + gap < len)
			{
				int temp = arr[end + gap];//temp临时变量代表将要插入的元素。
				//接下来就是组内进行插入排序。
				while (end >= 0)
				{
					if (arr[end] > temp)
					{
						arr[end + gap] = arr[end];//大于插入元素的往后移,它的位置空出来了。
						end -= gap;
					}
					else break;
				}

				arr[end + gap] = temp;
				end += gap;
			}
			
		}

		//接下来更新增量,进行下一轮排序。
		gap /= 2;
	}

	for (int i = 0; i < len; i++)
	{
		printf("%d ", arr[i]);
	}

	return 0;
}

这是AI的答案

#include <stdio.h>

int main()
{
    int arr[] = { 3, 2, 4, 9, 6, 1, 5, 7, 8 };
    int len = sizeof(arr) / sizeof(int);

    // 打印初始数组
    for (int i = 0; i < len; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("\n");

    // 希尔排序
    int gap = len / 2;  // 初始增量为数组长度的一半
    while (gap > 0)
    {
        // 从每组的起点出发
        for (int i = gap; i < len; i++)
        {
            int temp = arr[i];  // 当前待插入的元素
            int j = i;
            // 插入排序:对当前组进行排序
            while (j >= gap && arr[j - gap] > temp)
            {
                arr[j] = arr[j - gap];  // 元素后移
                j -= gap;
            }
            arr[j] = temp;  // 插入到正确位置
        }

        gap /= 2;  // 缩小增量
    }

    // 打印排序后的数组
    for (int i = 0; i < len; i++)
    {
        printf("%d ", arr[i]);
    }

    return 0;
}

ai这个好理解,将每组起点过后的元素进行插入排序,因为增量的存在,所以插入排序只会和自己所在组的进行比较。

另位博主写的代码

//希尔排序
void ShellSort(int* arr, int n)
{
	int gap = n;
	while (gap>1)
	{
		//每次对gap折半操作
		gap = gap / 2;
		//单趟排序
		for (int i = 0; i < n - gap; ++i)
		{
			int end = i;
			int tem = arr[end + gap];
			while (end >= 0)
			{
				if (tem < arr[end])
				{
					arr[end + gap] = arr[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			arr[end + gap] = tem;
		}
	}
}

二,链表相加

以前写的

Node* add_twolist(Node* head1, Node* head2)
{
	Node* ans, * current, * cur1 = head1, * cur2 = head2;
	ans = current = NULL;
	int carry = 0;
 
	for (
		int sum, val;
		cur1 != NULL || cur2 != NULL;
		cur1 = (cur1 == NULL) ? NULL : cur1->next,
		cur2 = (cur2 == NULL) ? NULL : cur2->next)
	{
		sum = (cur1 == NULL ? 0 : cur1->value)
			+ (cur2 == NULL ? 0 : cur2->value)
			+ carry;
 
		val = sum % 10;
		carry = sum / 10;
		
		if (ans == NULL)//create the new head node 
		{
			ans = new Node(val);
			current = ans;
		}
		else
		{
			current->next = new Node(val);
			current = current->next;
		}
 
	}
 
	if (carry == 1)current->next = new Node(1);
	return ans;
}

这是复习时写的

Node* add_list(Node* h1, Node* h2)
{
	Node* head, * current;
	int value, carry;

	value = (h1->value + h2->value) % 10;
	carry = (h1->value + h2->value) / 10;
	head = current = new Node(value);
	h1 = h1->next;
	h2 = h2->next;

	while (h1 && h2)
	{
		value = (h1->value + h2->value + carry) % 10;
		carry = (h1->value + h2->value + carry) / 10;
		Node* p = new Node(value);
		current->next = p;
		current = current->next;
		h1 = h1->next;
		h2 = h2->next;
	}

	while (h1)
	{
		value = (h1->value + carry) % 10;
		carry = (h1->value + carry) / 10;
		Node* p = new Node(value);
		current->next = p;
		current = current->next;
		h1 = h1->next;
	}

	while (h2)
	{
		value = (h2->value + carry) % 10;
		carry = (h2->value + carry) / 10;
		Node* p = new Node(value);
		current->next = p;
		current = current->next;
		h2 = h2->next;
	}

	if (carry)
	{
		Node* p = new Node(carry);
		current->next = p;
		current = current->next;
	}

	return head;
}

三,分割链表

第一次

Node* seperate_list(Node* head, int target)
{
	Node* h1, * h2, * cur1, * cur2;
	h1 = cur1 = NULL;
	h2 = cur2 = NULL;

	while (head)
	{
		if (head->value <= target)
		{
			if (!h1)h1= head;
			else
			{
				cur1->next = head;
				cur1 = cur1->next;
			}
		}
		else
		{
			if (!h2)h2 = cur2 = head;
			else
			{
				cur2->next = head;
				cur2 = cur2->next;
			}
		}

		head = head->next;
	}


	cur1->next = h2;
	return h1;
}

能看出哪里有问题吗?

首先是两条链表赋值时,只让h1 = head,此时cur1还是NULL;

cur2的next可能没有指向空,导致打印链表时出现死循环。

例如数组int arr[] = { 3,2,6,5,4,7,1 };

还有第三个错误就是没有新造链表,直接使用原链表,原链表的节点之间的联系还没有解开,关系混乱。

改后

Node* seperate_list(Node* head, int target)
{
	Node* h1, * h2, * cur1, * cur2;
	h1 = cur1 = NULL;
	h2 = cur2 = NULL;

	while (head)
	{
		if (head->value < target)
		{
			if (!h1)h1 = cur1 = new Node(head->value);
			else
			{
				cur1->next = new Node(head->value);
				cur1 = cur1->next;
			}
		}
		else if(head->value > target)
		{
			if (!h2)h2 = cur2 = new Node(head->value);
			else
			{
				cur2->next = new Node(head->value);
				cur2 = cur2->next;
			}
		}

		head = head->next;
	}


	cur1->next = new Node(target);
	cur1 = cur1->next;
	cur1->next = h2;
	if (!cur2) cur2->next = NULL;
	return h1;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2271627.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从零开始RTSP协议的实时流媒体拉流(pull)的设计与实现(一)

此文为系列文章&#xff0c;此系列主要讲解RTSP客户端的拉流及播放&#xff0c;文章持续更新&#xff0c;会从rtsp的基本协议讲起&#xff0c;如何一步步实现音视频的拉流过程&#xff0c;包括一系列涉及到的协议&#xff0c;rtsp&#xff0c;sdp&#xff0c; rtp&#xff08;本…

量子力学复习

黑体辐射 热辐射 绝对黑体&#xff1a; &#xff08;辐射能力很强&#xff0c;完全的吸收体&#xff0c;理想的发射体&#xff09; 辐射实验规律&#xff1a; 温度越高&#xff0c;能量越大&#xff0c;亮度越亮 温度越高&#xff0c;波长越短 光电效应 实验装置&#xf…

如何排查 Apache Doris 中 “Failed to commit txn“ 导入失败问题?

今天来聊聊 Doris 数据导入那些事儿。你是不是在数据导入的时候遇到各种状况&#xff0c;让人头疼不已&#xff1f;别担心&#xff0c;这篇文章给你答案&#xff01; 在 Doris 的版本里&#xff0c;< 2.0.3 的时候&#xff0c;数据迁移存在一些已知的问题&#xff0c;比如可…

基于AT89C51单片机的可暂停八路抢答器设计

点击链接获取Keil源码与Project Backups仿真图&#xff1a; https://download.csdn.net/download/qq_64505944/90196607?spm1001.2014.3001.5503 C15 部分参考设计如下&#xff1a; 摘要 随着社会进步和科技发展&#xff0c;电子设备在各类活动中的应用日益普遍&#xff0c…

OSCP - Proving Grounds - Pelican

主要知识点 当信息多的时候&#xff0c;耐心搜索Zookeeper exhibitor RCE漏洞 具体步骤 依旧执行Nmap Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-13 22:44 UTC Nmap scan report for 192.168.54.98 Host is up (0.00090s latency). Not shown: 65526 closed …

计算机毕业设计PyHive+Hadoop深圳共享单车预测系统 共享单车数据分析可视化大屏 共享单车爬虫 共享单车数据仓库 机器学习 深度学习

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

WebRtc01:课程导学、框架介绍

应用 难点 课程大纲 学习收获 涉及内容 概述 用途 学习收获

特殊车辆检测数据集VOC+YOLO格式2730张3类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;2730 标注数量(xml文件个数)&#xff1a;2730 标注数量(txt文件个数)&#xff1a;2730 …

【AI日记】25.01.04 kaggle 比赛 3-3 | 王慧玲与基层女性

【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】 工作 参加&#xff1a;kaggle 比赛 Forecasting Sticker Sales时间&#xff1a;6 小时 读书 书名&#xff1a;基层女性时间&#xff1a;3 小时原因&#xff1a;虽然我之前就知道这个作者&#xff0c;因为我…

电子应用设计方案85:智能 AI门前柜系统设计

智能 AI 门前柜系统设计 一、引言 智能 AI 门前柜系统旨在提供便捷、安全和智能的物品存储与管理解决方案&#xff0c;适用于家庭、公寓或办公场所的入口区域。 二、系统概述 1. 系统目标 - 实现无接触式物品存取&#xff0c;减少交叉感染风险。 - 具备智能识别和分类功能&am…

GOGOGO 抽象

抽象其实也算面向对象特征之一 抽象 含义&#xff1a;当多个子类中的共性向上提取&#xff0c;父类中不知道如何写具体实现&#xff0c;因为提取的共性并不一定能解决子类中实现的功能【同结构不一定同实现代码体】&#xff0c;就需要抽象概念 作用 父类只抽取结构&#xff…

【模型】Qwen2-VL 服务端UI

1. 前言 最近在测试VLM模型&#xff0c;发现官方的网页demo&#xff0c;代码中视频与图片分辨率可能由于高并发设置的很小&#xff0c;导致达不到预期效果&#xff0c;于是自己研究了一下&#xff0c;搞了一个简单的前端部署&#xff0c;自己在服务器部署了下UI界面&#xff0…

IEEE PDF eXpress遇到Font TimesNewRomanPSMT is not embedded的解决方案

IEEE PDF eXpress遇到Font TimesNewRomanPSMT is not embedded的解决方案 问题描述 在IEEE PDF eXpress上上传论文后&#xff0c;出现Font XXX is not embedded的问题。 该问题是指你所插入的图片等&#xff0c;没有将对应的字体嵌入进去。 解决方案 以下以Origin Lab图片…

【Ubuntu】 Ubuntu22.04搭建NFS服务

安装NFS服务端 sudo apt install nfs-kernel-server 安装NFS客户端 sudo apt install nfs-common 配置/etc/exports sudo vim /etc/exports 第一个字段&#xff1a;/home/lm/code/nfswork共享的目录 第二个字段&#xff1a;指定哪些用户可以访问 ​ * 表示所有用户都可以访…

简易Type-C拉取5V/3A电流电路分享

今天介绍一种在Type-C 5V电压下获取3A电流的简易办法 我们都知道&#xff0c;USB里面的D D-用来传输数据&#xff0c;其实Type-C接口里面还有一组CC引脚&#xff0c;先科普一些概念 DFP&#xff0c;下行端口&#xff0c;可以理解为Host&#xff0c;数据下行以及对外提供电源&…

uni-app深度解码:跨平台APP开发的核心引擎与创新实践

在当今数字化浪潮中&#xff0c;移动应用市场呈现出爆炸式增长。为了满足不同用户群体在不同操作系统上的需求&#xff0c;跨平台 APP 开发成为众多开发者的首选策略。uni-app 作为一款领先的跨平台开发框架&#xff0c;以其独特的优势和创新的实践在众多同类产品中脱颖而出。它…

C#运动控制系统:雷赛控制卡实用完整例子 C#雷赛开发快速入门 C#雷赛运动控制系统实战例子 C#快速开发雷赛控制卡

雷赛控制技术 DMC系列运动控制卡是一款新型的 PCI/PCIe 总线运动控制卡。可以控制多个步进电机或数字式伺服电机&#xff1b;适合于多轴点位运动、插补运动、轨迹规划、手轮控制、编码器位置检测、IO 控制、位置比较、位置锁存等功能的应用。 DMC3000 系列卡的运动控制函数库功…

Spring Boot + Redis + Sa-Token

参考文献 Sa-Token实现分布式登录鉴权&#xff08;Redis集成 前后端分离&#xff09;-腾讯云开发者社区-腾讯云 介绍 StpInterface 是 Sa-Token 框架中的一个接口&#xff0c;属于 Sa-Token 身份认证与授权框架的一部分。该接口提供了一些方法来实现自定义的身份认证和授权管…

智慧工地信息管理与智能预警平台

建设背景与政策导向 智慧工地信息管理与智能预警平台的出现&#xff0c;源于工地管理面临的诸多挑战&#xff0c;如施工地点分散、危险区域多、监控手段落后等。随着政府对建筑产业现代化的积极推动&#xff0c;各地纷纷出台政策支持智慧工地的发展&#xff0c;旨在通过信息技…

GoF23种设计模式 简介

文章目录 面向对象(OO)设计原则&#xff08;7&#xff09;单一职责原则开闭原则里氏代换原则依赖倒转原则接口隔离原则合成复用原则迪米特法则 创建型模式 &#xff08;5&#xff09;工厂方法模式 &#xff08;类模式&#xff0c;其余都是对象模式&#xff09;抽象工厂模式建造…