数据结构中的排序

数据结构学习分享

  1. 落笔于此,我静坐于江理图书馆六楼朝南的落地窗前。窗外行人往来络绎,步履匆匆,皆是奔赴各自的前路,人间烟火喧嚣,却衬得窗内的我愈发沉静,也愈发茫然。方才,我堪堪结束了数据结构阶段的学习。这门功课的晦涩艰深,远不止于代码与逻辑的繁杂难懂,更像一把钝刀,缓缓剖开我心底关于理想与世俗的混沌,逼我直面内心最真实的迷茫。
  2. 此番学习,我依托粤嵌配套教程深耕精进,李明轩老师的授课条理清晰、深入浅出,为我拨开了技术学习的重重迷雾。课程要求每位同学搭建个人技术博客,也正因这个契机,我得以翻阅往届学长学姐的文字与足迹。可浏览之余,一股浓烈的虚无感悄然裹挟了我。我发现,绝大多数人的博客记录,都定格在了2024年五月,及至九月便彻底停更,再无更新。那些曾经热烈的学习痕迹、真挚的成长感悟,短短数月便戛然而止,如同无数热烈的奔赴,最终都悄然湮灭在岁月之中。
  3. 我不禁陷入长久的沉思。我们奔波求学、日夜精进,日夜奔赴的前路,终极意义究竟是什么?难道世人穷尽青春、耗尽心力的追求,终究只是为了赚得满目钱财?身处当下的时代洪流,我们自年少时便被世俗规训,被潜移默化地灌输“有钱便是人上人”的功利准则。久而久之,欲望取代了初心,功利裹挟了本心,我们所谓的理想,渐渐沦为了谋生的工具、逐利的任务。
    可回望来路,我才惊觉,每个人心底,都曾藏有一份纯粹无瑕的理想,不掺世俗烟火,不染功利尘埃。
  4. 年少懵懂的小学时代,我的理想是成为一名警察。彼时的心愿简单而赤诚,无关名利、不问前程,只是由衷敬佩警察惩恶扬善、守护四方的模样,只想凭一己之力守护正义。步入初中,我沉醉于数学的逻辑之美,数字与公式间的推演、逻辑与规律的碰撞,让我心生热忱,便立志成为一名数学家,深耕所爱,探索未知。及至高中,我向往长空万里的辽阔,渴望成为一名飞行员,冲破云层、翱翔天际,在疾风与苍穹之间,感受速度的热烈、自由的坦荡。
  5. 可岁月流转,年岁渐长,那些纯粹热烈、发自本心的理想,终究在世俗的喧嚣中慢慢褪色、悄然逝去。曾经滚烫的热爱,被现实的功利层层覆盖;原本纯粹的追求,被谋生的欲望彻底替代。如今支撑我前行的,再也不是心底的热爱与向往,而是世俗赋予的、任务式的功利目标。我日复一日地学习、刷题、精进,看似步履不停,实则只是被动完成欲望下达的指令,麻木地追赶世人定义的“成功”。
  6. 直至今日,我终于幡然醒悟,这般被欲望裹挟的理想,从来无法真正支撑人生的长路。它无法抚平求学的疲惫,无法消解内心的荒芜,更无法让我在迷茫中寻得方向。这般功利的执念,看似是前行的动力,实则是无形的枷锁,只会让人在追逐名利的路上愈发疲惫、愈发空洞。于是在这一刻,我彻底丧失了追逐世俗欲望的所有动力。
  7. 浮躁散尽,心绪渐平,我终于勘破其中真谛。人生于世,最可贵的从不是追名逐利、跻身世俗定义的“高处”,而是守住一份纯正的本心与理想。每个人都该有专属自己的热爱与坚守,有不被世俗裹挟的追求,有不随波逐流的初心。
  8. 若是一生困于世俗规训,缚于功利欲望,舍弃本心、磨灭热爱,便如同无根之木、无源之水。看似步步前行、步步精进,实则早已坠入精神荒芜的万丈深渊,终其一生,皆在空洞的奔波中虚度,终生碌碌,却无半分心安与圆满。

一、数据结构的特点:

  1. 算法的五要素:输入,输出,可行性,有穷性,确定性
  2. 数据结构的两类结构
    • 存储结构:顺序存储和链式存储
    • 逻辑结构:线性结构和非线性结构
  3. 衡量算法好坏的数据:时间复杂度(完成任务所需要的执行语句的次数)
  4. 算法的计量单位:复杂度

二、数据结构中的几种常见(用的数据结构)

1.顺序表:

1.1顺序表的特点总结:

  1. 顺序表一般是指用数组加上一个管理数组两种结构体定义的数据。
  2. 顺序表的特点是可以通过下标的方式去进行遍历的动作,但是想要增删是比较难的
  3. ** 接下来进行代码演示:**
/**
  *  Founction:创建一个顺序表
  *  Aurthor  : CKS
  *  Date     :2026.9.22
  *  Arguement:
  *  Return   :none
  *  note     :none
  *  
  * Copyright(c)     2706777938@qq.com       All Rights Reserved
  */
//先把用户需要存的数据给宏定义,千万不能把目标写死。
typedef int RealData_t;//后续用户可以把这里的int换成他自己想要的数据类型。
//定义一个用来存顺序表的首元素地址,列表空间,列表最后元素下标
typedef struct ListAbout
{
  int size;
  int last;
  RealData_t*head;  
}Manager_t;

//创建顺序表并对顺序表进行初始化
Manager_t* ListMake(unsigned int size)
{
  //先为管理申请一块内存
  Manager_t*Manager=(Manager_t*)calloc(1,sizeof(Manager_t));
  //注意每次申请堆内存必须做错误处理,防止段错误。
  if(Manager=NULL){ 
    perror("replay memory for Manager flase:");
    return NULL;
  } 
  //给顺序表存储的元素申请内存
  Manager->head=(RealData_t*)calloc(size,sizeof(RealData_t));
  //这里有一个大坑
  if(Manager->head=NULL){
    perror("replay memory for Manager flase:");
    return NULL;
  }
  Manager->size=size;
  Manager->last=-1;//这里让尾元素下表指向-1有大用处
  return Manager;
}

//构建一个判断列表是否已经满了的函数
bool FullJudg(Manager_t*manager)
{

  if(manager->size==manager->last+1)
    return true;
  return false;
}

//头插数据,传入管理的地址
bool HeadInsert(Manager_t*Manager,RealData_t data)
{	
  //先用循环把数据整体往后移
  //因为要把数据往后移动,所以先调用函数判断数组满了没有:
  if(FullJudg(Manager)){
  printf("this list is full\n");
  return false;
  }
  for (int i = 0; i < Manager->last+1; ++i)
  *(Manager->last+1-i)=*(Manager->last-i);
  
  *(Manager->head)=data;
  Manager->last++;
  return true;  
}

//尾部插入数据
bool BackInsert(Manager_t*Manager,RealData_t data)
{
 //先判断列表有没有满
  if(true==FullJudg(Manager))
      return false;
    //处理正常情况下的尾插。

  *(Manager->head+last+1)=data;
  Manager->last++;
  return true;  
}

//头部删除
bool HeadDelect(Manager_t*manager)
{
   //正常用后值覆盖第一个值
     for (int i = 0; i < manager->last; ++i){
    *(manager->head+i)=*(manager->head+1+i); 
    return true;
  }
  manager->last--;
  return true;

}

//尾部删除
bool BackDelect(Manager_t*manager)
{
  //直接删除最后一个元素就行了
  if(manager->last==-1)
    return true;
  //剩下正常情况进行处理即可
  manager->last--;
  return true;
}

//对整个顺序表进行遍历
bool AllPrint(Manager*manager)
{
  for (int i = 0; i < manager->last; ++i)
  {
    printf("\n");
  }
}

2.链表

2.1单向链表

代码演示:

/***********************************************************************
 *  Founction:创建一个链式表
 *  Aurthor  : CKS
 *  Date     :2026.9.15
 *  Arguement:
 *  Return   :none
 *  note     :none
 *  
 * Copyright(c)     2706777938@qq.com       All Rights Reserved
 **********************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
//先创建一个链式表要存储的数据的类型
typedef int RealData;

typedef struct GoalData
{
	RealData realdata;
	struct GoalData *Next;
}Data;

//先创建一个头结点
Data *HeadMake()
{
	//用calloc申请一块地址给头节点
	Data * Head=(Data*)calloc(1,sizeof(Data));
	if(Head =NULL){
		perror("sign HeadMake flase: ");
		return NULL;
	} 
	return Head;
}

//创建一个新结点
Data * NewMake(Data data)
{
		Data * Goal =(Data*)calloc(1,sizeof(Data));
		//初始化数据
		if(Goal =NULL){
		perror("sign Goal flase: ");
		return NULL;
		} 
		//把用户需要存的数据插入到新结点中
		Goal->realdata=data;
		return Goal;		
}

//将数据头插入
bool HeadInsert(Data*head,Data*goal)
{
//判断链表是否为空
	if (head->Next==NULL){
		head->Next==goal;
		return true;
	}

//不为空的情况下,先断开首节点和头节点的连节
	goal->Next=head->Next;
	//把新加入的数据连上头节点
	head->Next=goal;
	return true;
}

/*//将数据插入到指定数据后面
bool PointInsert(Data*head,Data*goal)
{
//先通过遍历把对应的数据找出
	while(head->realdata!=goal->realdata){
		head =head->Dest;

	}
	if (head==NULL)
	{
		printf("原链表没有这个数据");
		return false;
	}

//找到之后把数据重连
	goal->Dest=head ->Dest;
	head->Dest=goal;
	return true;
}
*/

//把数据插到末尾
bool EndInsert(Data*head,Data*goal)
{
//先用遍历找到尾结点
	Data *phead=head;
	while(phead->Next)
		phead =phead->Next;
	//把数据插如到尾部即可
	phead->Nest=goal;
	return true;
}

//头删数据
bool HeadDelet(Data*head)
{	//先拷贝首节点的地址
	if (head->Next==NULL)
		return true;
	Data *phead=head->Next;
	//先把新的首结点和头节点连上
	head->Next==head->Next->Next;
	phead->Next=NULL;
	free(phead);
	return true; 
}

//尾删除数据
bool BackDelect(Data*head)
{
	if (head->Next==NULL)
		return true;
	//考虑普通情况
	//先用遍历找到尾结点
	Data *phead=head;
	while(phead->Next->Next)
		phead =phead->Nest;
	free(phead->Next);
	phead->Next=NULL;
}

//遍历数据
bool AllPrint(Data*head)
{
 	while(head->Next){
 		printf("%s\n", );
 	}
 	printf();
}

2.2单向循环链表

代码演示:

/**********************************************************************
 *  Founction:创建一个单向循环链式表
 *  Aurthor  : CKS
 *  Date     :2026.9.22
 *  Arguement:
 *  Return   :none
 *  note     :none
 *  
 * Copyright(c)     2706777938@qq.com       All Rights Reserved
 **********************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
//先创建一个链式表要存储的数据的类型
typedef int RealData;
typedef struct FaceData
{
	RealData realdata;
	struct FaceData *Dest;
}Data;

//先创建一个头结点
Data *HeadMake()
{
	Data * Head=(Data*)calloc(1,sizeof(Data));
	if(Head =NULL){
		perror("sign HeadMake flase: ");
		return NULL;
		} 
	return Head;
}

//创建一个数据。
Data * NewDataMake(RealData real)
{

		Data * Goal =(Data*)calloc(1,sizeof(Data));
		//初始化数据
		if(Goal =NULL){
		perror("sign Goal flase: ");
		return NULL;
		} 
		Goal->realdata=real;
        Goal->Dest=Goal;
		return Goal;
}

//将创建好的数据头插入
bool HeadInsert(Data*head,Data*goal)
{
	//先判断是不是空的链表
	if (head->Dest=NULL){
	head->Dest=goal;
	return true;
	}
	//剩下正常把数据头插入
	//先找到尾巴
	Data*phead=head;
	while(phead->Dest!=head)
		phead->Dest=phead->Dest->Dest;
	goal->Dest=head->Dest;
	head->Dest=goal;
	phead->Dest=goal;
	return true;
}

/*
//将数据插入到指定数据后面
bool PointInsert(Data*head,Data*goal)
{
//先通过遍历把对应的数据找出
	while(head->realdata!=goal->realdata){
		head =head->Dest;

	}
	if (head==NULL)
	{
		printf("原链表没有这个数据");
		return false;
	}

//找到之后把数据重连
	goal->Dest=head ->Dest;
	head->Dest=goal;
	return true;
}
*/

//把数据插到末尾
bool EndInsert(Data*head,Data*goal)
{
	Data *phead=head;	
//先用遍历找到尾结点
	while(phead->Dest!=head)
		phead =phead->Dest;
	//把数据插如到尾部即可
	phead->Dest=goal;
	//把数据重连
	goal->Dest=head->Dest;
	return true;
}

//头删文件
bool HeadDelet(Data*head)
{	//先判断链表是不是空的
	if (head->Dest==NULL)
		return true;
	//判断是不是只有首届点
	if (head->Dest->Dest==head->Dest){
		head->Dest->Dest=NULL;
		free(head->Dest);
		head->Dest=NULL;
	}
	//把数据节点先进行链接
	Data*phead=head;
	while(phead->Dest!=head)
		phead->Dest=phead->Dest->Dest;
	head->Dest=head->Dest->Dest;
	Data*pheadnext=phead->Dest;
	phead->Dest=head->Dest;
	pheadnext->Dest=NULL;
	free(pheadnext);
	return true; 
}

//尾删
bool BackDelet(Data*head)
{	//先判断链表是不是空的
	if (head->Dest==NULL)
		return true;
	//判断是不是只有首结点
	if (head->Dest->Dest==head->Dest){
		free(head->Dest);
		return true;
	}
	//在一般的情况下
	//先遍历找到尾结点
	Data*phead=head;
	while(phead->Dest->Dest!=head){
		phead->Dest=phead->Dest->Dest;
	}
	phead->Dest->Dest=NULL;
	free(phead->Dest);
	phead->Dest=head->Dest;
	return true; 
}

2.3双向链表

代码演示:

/**
  *  Founction:创建一个双向链表
  *  Aurthor  : CKS
  *  Date     :2026.9.22
  *  Arguement:
  *  Return   :none
  *  note     :none
  *  
  * Copyright(c)     2706777938@qq.com       All Rights Reserved
**/
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>

//先创建一个链式表要存储的数据的类型
typedef int RealData;

typedef struct GoalData
{
	RealData realdata;
	struct GoalData *Next;
	struct GoalData *Prev;
}Data;

//先创建一个头结点
Data *HeadMake()
{
	Data * Head=(Data*)calloc(1,sizeof(Data));
	if(Head =NULL){
	perror("sign HeadMake flase: ");
	return NULL;
	} 
	return Head;
}

//创建一个数据。
Data * GoalMake(RealData realdata)
{
		Data * Goal =(Data*)calloc(1,sizeof(Data));
		//初始化数据
		if(Goal =NULL){
		perror("sign Goal flase: ");
		return NULL;
		} 
		Goal->realdata=realdata;
		return Goal;
}

//将创建好的数据头插入
bool HeadInsert(Data*head,Data*goal)
{
	//先判断链表是不是空的
	if (head->Next==NULL)
	{
		head->Next=goal;
		return true;
	}
	//现在处理普通情况
	//先把首结点指向新节点
	head->Next->Prev=goal;
	//再把新节点下节点指向首届点
	goal->Next=head->Next;
	//把头节点指向新节点
	head->Next=goal;
	return true;
}

//把数据插到末尾
bool EndInsert(Data*head,Data*goal)
{
		//判断是不是空链表的情况
		if (head->Next==NULL)
		{
			head->Next=goal;

			return true;
		}
//先用遍历找到尾结点
		while(head->Next){
		head =head->Next;
		}
		head->Next=goal;
		goal->Prev=head;
		return true;

}
		//把头节点后面一个元素给删除
	bool HeadDelet(Data*head)
	{
		//先判断是不是空链表
		if (head->Next==NULL)
		{
			return true;
		}
		//普通情况下
		//拷贝首届点地址
		Data*phead=head->Next;
		//先把新首结点前指针删除
		head->Next->Next->Prev=NULL;
		//再把新首届点和head链接
		head->Next=head->Next->Next;
		//删除原来首届点
		phead->Next=NULL;
		free(phead);
		return true; 
	}
		//进行尾部删除
	bool HeadDelet(Data*head)
	{
		//先排除特殊情况
		if (head->Next== NULL)
		{
			return true;
		}
		//先找到尾部节点
		while(head->Next){
		head =head->Next;
		}
		head->Prev->Next=NULL;
		head->Prev=NULL;
		free(head);
		return true; 
	}
//进行遍历输出	

2.4双向循环链表

代码演示:

/**
  *  Founction:创建一个双向循环链表
  *  Aurthor  : CKS
  *  Date     :2026.9.15
  *  Arguement:
  *  Return   :none
  *  note     :none
  * Copyright(c)     2706777938@qq.com       All Rights Reserved
**/
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>

//先创建一个链式表要存储的数据的类型
typedef int RealData;
typedef struct GoalData
{
	RealData realdata;
	struct GoalData *Next;
	struct GoalData *Prev;
}Data;

//先创建一个头结点
Data *HeadMake()
{
	Data * Head=(Data*)calloc(1,sizeof(Data));
	if(Head ==NULL){
	perror("sign HeadMake flase: ");
	return NULL;
	} 
	return Head;
}

//创建一个数据。
Data * GoalMake(RealData realdata)
{

		Data * Goal =(Data*)calloc(1,sizeof(Data));
		//初始化数据
		if(Goal ==NULL){
		perror("sign Goal flase: ");
		return NULL;
		} 
		Goal->realdata=realdata;
		return Goal;
}

//将创建好的数据头插入
bool HeadInsert(Data*head,Data*goal)
{
	//先判断链表是不是空的
	if (head->Next==NULL)
	{
		head->Next=goal;
		goal->Next=goal;
		goal->Prev=goal;
		return true;
	}
	//现在处理普通情况
	//把尾结点和首结点连上
	head->Next->Prev->Next=goal;
	//先把首结点指向新节点
	head->Next->Prev=goal;
	//再把新节点下节点指向首届点
	goal->Next=head->Next;
	//把头节点指向新节点
	head->Next=goal;
	return true;
}

//把数据插到末尾
bool EndInsert(Data*head,Data*goal)
{
	//先判断链表是不是空的
	if (head->Next==NULL)
	{
		head->Next=goal;
		goal->Next=goal;
		goal->Prev=goal;
		return true;
	}
	//先把为元素和新元素建立对应的联系
	head->Next->Prev->Next=goal;
	goal->Prev=head->Next->Prev;
	//再把新的尾结点和首结点连上
	goal->Next=head->Next;
	return true;
	}
//把头节点后面一个元素给删除
bool HeadDelet(Data*head)
{
		//先判断是不是空链表
		if (head->Next==NULL)
		{
			return true;
		}
		//判断是不是只有一个首结点
		if(head->Next==head->Next->Next)
		free(head->Next);
		//普通情况下
		//拷贝首届点地址
		Data*phead=head->Next;
		//先把新首结点前指针删除
		head->Next->Next->Prev=head->Next->Prev;
		//把尾结点指向新首结点
		head->Next->Prev->Next=head->Next->Next;
		//再把新首届点和head链接
		head->Next=head->Next->Next;
		phead->Next=NULL;
		phead->Prev=NULL;
		//删除原来首届点
		free(phead);
		return true; 
	}

//进行尾部删除
bool HeadDelet(Data*head)
{
		//先排除特殊情况
		if (head->Next==NULL)
			return true;
		if(head->Next-Prev==head->Next){
		head->Next->Next=NULL;
		head->Next->Prev=NULL;
		free(head->Next);
		head->Next=NULL;
		return true;
		}
		Data*phead=head->Next->Prev->Prev;
		head->Next->Prev->Prev->Next=head->Next;
		head->Next->Prev=head->Next->Prev->Prev;
		phead->Next=NULL;
		phead->Prev=NULL;
		free(phead);
		return true; 
	}
//进行遍历输出	

3.栈

3.1顺序栈

代码实现

/**
  *  Founction:创建一个顺序栈
  *  Aurthor  : CKS
  *  Date     :2026.9.18
  *  Arguement:
  *  Return   :none
  *  note     :none
  * Copyright(c)     2706777938@qq.com       All Rights Reserved
  */

//先把用户需要存的数据给宏定义
typedef int RealData_t;
//定义一个用来存顺序表的首元素地址,列表空间,列表最后元素下标
typedef struct ListAbout
{
  int size;
  int last;
  RealData_t*head;  
}Manager_t;
//创建顺序表并对顺序表进行初始化
Manager_t* ListMake(unsigned int size)
{
  //先为管理申请一块内存
  Manager_t*Manager=(Manager_t*)calloc(1,sizeof(Manager_t));
  //判断有没有出问题
  if(Manager=NULL){ 
    perror("replay memory for Manager flase:");
    return NULL;
  } 
  //给顺序表存储的元素申请内存
  Manager->head=(RealData_t*)calloc(size,sizeof(RealData_t));
  //这里有一个大坑
  if(Manager->head=NULL){
    perror("replay memory for Manager flase:");
    return NULL;
  }
  Manager->size=size;
  Manager->last=-1;
  return Manager;
}

//构建一个判断列表是否已经满了的函数
bool FullJudg(Manager_t*manager)
{

  if(manager->size==manager->last+1)
    return true;
    return false;
}

//入栈Push
bool BackInsert(Manager_t*Manager,RealData_t data)
{
 //先判断列表有没有满
  if(FullJudg(Manager))
      return false;
    //处理正常情况下的尾插。
  *(Manager->head+last+1)=data;
  Manager->last++;
  return true;
}

//出栈pop
bool BackDelect(Manager_t*manager)
{
  if(manager->last==-1)
    return true;
  //剩下正常情况进行处理即可
  printf("%d",*(manager->head->last->head));
  manager->last--;
  return true;
}

4.队列

4.1.循环队列

代码实现

/**
  *  Founction:利用顺序表实现一个队列
  *  Aurthor  : CKS
  *  Date     :2026.9.19
  *  Arguement:
  *  Return   :none
  *  note     :none
  * Copyright(c)     2706777938@qq.com       All Rights Reserved
  */
//先给用户数据格式T一下
typedef int Data;
//定义一个结构体存储队列的rear和front
typedef struct QueueManager
{
  Realdata*Front;
  Realdata*Rear;
  int size;
}Manager;

//创建一个列表管理结构体和对应队列
Manager*ManagerMaker(int size)
{
  Manager*manager=(Manager*)calloc(1,sizeof(Manager));
  //进行错误判断
  if (manager==NULL)
  {
    perror("calloc for New is false:");
    return NULL;
  }
  //给队列申请一块内存
  Data*data=( Data*)calloc(size,sizeof(Data));
    //进行错误判断
  if (data==NULL)
  {
    perror("calloc for New is false:");
    return NULL;
  }
  manager->Rear=data;
  manager->Front=data;  
  return manager;
}

//往队列里面插入新数据
bool InsertQueue(Manager*manager,Data*data)
{ //先判断队列有没有满
  if((manager->Rear+1)%(manager->size)==manager->Front){
    printf("数据已经满了");
    return false;
  }
  *(manager->Rear)=data;
  manager->Rear=(manager->Rear++)%(manager->size);
  return true;
}

//出队
bool InsertQueue(Manager*manager,Data*data)
{
  //先判断是不是空的队列
  if(manager->Rear==manager->Front){
    printf("已经是空的列表了\n");
    return true;
  }
  //处理一般的情况
  *(manager->Front)=0;
  manager->Front=(manager->Front+1)%(manager->size);
}

5.二叉树

5.1.二叉查找树

代码演示

/**
  *  Founction:利用链表实现一个栈
  *  Aurthor  : CKS
  *  Date     :2026.9.19
  *  Arguement:
  *  Return   :none
  *  note     :none
  * Copyright(c)     2706777938@qq.com       All Rights Reserved
  */
//先创建二叉树数据对应的结构体
typedef struct BinTree{
  int num;
  struct BinTree*Left;
  struct BinTree*Right;
}Data;
//创建一个二叉树数据
Data* DataMaker()
{
  Data*data=(Data*)calloc(1,sizeof(Data));
  if(data==NULL){
    perror("calloc is faulor:");
    return NULL;
  }
  return data;
}
//创建一个新数据
Data* NewDataMaker(int new)
{
  Data*data=(Data*)calloc(1,sizeof(Data));
  if(data==NULL){
    perror("calloc is faulor:");
    return NULL;
  }
  data->num=new;
  return data;
}
//把数据插入二叉树
bool InsertData(Data*head,Data*data)
{ //判断树杈是否为空
  if (head->num==0)
  {
    head->num=data;
    return true;
  }
  //先直接遍历找到最终的位置
  //建一个变量来存结束位置前一个地址
  Data*Rphead=NULL;
  Data*Lphead=NULL;
  while(head){
    //判断数据和当前位置的数据的大小并做出对应的处理
    if(head->num<data->num){
      head=head->Right;
      Rphead=head;
      continue;
    }
    else if(head->num>data->num){
      head=head->Left;
      Lphead=head;
      continue;
    }
    else{
      printf("插入错误,您的数已经存在\n");
      return false;
    }
    //现在直接在head后面插入数据即可
    if (Lphead->Left==NULL)
    {
      Lphead->Left=data;
      return true;
    }
    if (Rphead->Right==NULL)
    {
      Rphead->Right=data;
      return true;
    }
}
//删除二叉树的结点
//由于这个过于复杂,只讲思路:把被删除点地左子树中最大值或右子树中最小值拿来顶替即可

6.排序

6.1.插入排序

代码实现

/**
  *  Founction:插入排序
  *  Aurthor  : CKS
  *  Date     :2026.9.19
  *  Arguement:
  *  Return   :none
  *  note     :none 
  * Copyright(c)     2706777938@qq.com       All Rights Reserved
  */
#include<stdio.h>
#include<stdbool.h>
bool InsertSort(int num[],int n)
{
  for (int i = 1; i < n; ++i)
  {   //定义一个变量来存第i个的数据
    int cpnum=num[i];
    int j;
    for ( j = i-1; j >=0; j--)
    { 
      //现在比较两个数的大小
      if (num[j]<cpnum)
      {
        break;
      }
      else{
        num[j+1]=num[j];
      }
    }
    num[j+1]=cpnum;
  }
  return true;
}

6.2.冒泡排序

代码实现

//冒泡排序 ,指的是元素两两之间进行比较交换,需要比较n轮,每轮需要比较m次,从左向右升序
void bubbleSort(int buf[],int bufsize)
{
  int temp = 0; //为了临时存储交换值

  //1.循环比较元素,需要比较n轮
  for (int n = 1; n < bufsize; ++n)
  {
    //2.每轮需要比较m次
    for (int m = 0; m < bufsize-n; ++m)
    {
      //3.数组元素两两之间进行比较交换 buf[0] buf[1]  buf[1] buf[2]
      if (buf[m] > buf[m+1])
      {
        temp   = buf[m];   //备份前一个
        buf[m] = buf[m+1]; //把后面交换到前面
        buf[m+1] = temp;   //把前面交换到后面
      }
    }
  }
}

6.3.选择排序

代码实现

/**
  *  Founction:选择排序
  *  Aurthor  : CKS
  *  Date     :2026.9.19
  *  Arguement:
  *  Return   :none
  *  note     :none
  * Copyright(c)     2706777938@qq.com       All Rights Reserved
  */
//选择排序

#include<stdio.h>
#include<stdbool.h>




// 选择排序-升序
void selectSort(int arr[], int n) {
    int i, j, minIndex, temp;
    for (i =< n - 1; i++) {
        minIndex = i; // 假设当前下标为最小值下标
        // 遍历未排序区间,找最小值下标
        for (j = i +< n; j++) {
            if (arr[j] < arr[minIndex]) {
                minIndex = j;
            }
        }
        // 交换最小值与未排序首位
        if (minIndex != i) {
            temp = arr[i];
            arr[i] = arr[minIndex];
            arr[minIndex] = temp;
        }
    }
}

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

int main() {
    int arr[] = {5,2,9,1,3};
    int len = sizeof(arr) / sizeof(arr[0]);
    selectSort(arr, len);
    printArr(arr, len);
    return 0;
}

6.4.简易快速排序(难点)

代码实现

/**
  *  Founction:17.简易快速排序
  *  Aurthor  : CKS
  *  Date     :2026.9.19
  *  Arguement:
  *  Return   :none
  *  note     :none
  *  
  * Copyright(c)     2706777938@qq.com       All Rights Reserved
  */

//简易快速排序是利用递归的方式通过确定一个基准先把基准位置找好
#include <stdio.h>

void quickSort(int arr[], int left, int right)
{
    if(left >= right)
        return;

    int pivot = arr[left]; // 选最左边作为基准
    int l = left, r = right;

    while(l < r)
    {
        // 右指针找小于pivot的
        while(l < r && arr[r] >= pivot)
            r--;
        arr[l] = arr[r];

        // 左指针找大于pivot的
        while(l < r && arr[l] <= pivot)
            l++;
        arr[r] = arr[l];
    }
    arr[l] = pivot; // 基准归位

    quickSort(arr, left, l - 1);  // 递归左区间
    quickSort(arr, l + 1, right); // 递归右区间
}


三.数据结构中其他常用的知识点

1.运用递归计算节点数

代码演示

/**
  *  Founction:12通过递归找二叉树的叶子数和节点个数和树地深度
  *  Aurthor  : CKS
  *  Date     :2026.9.19
  *  Arguement:
  *  Return   :none
  *  note     :none
  *  
  * Copyright(c)     2706777938@qq.com       All Rights Reserved
  */

include<stdio.h>


//先创建二叉树数据对应的结构体
typedef struct BinTree{
  int num;
  struct BinTree*Left;
  struct BinTree*Right;


}Data;
//先实现用二叉树计算树的结点数
  int TlNumNodes(Data*head)
  {
    //先设置终止条件
    if (NULL==head)
    {
      return 0;
    }
    //现在把普通的情况写出
    n1 =TlNumNodes(head->Left);
    n2 =TlNumNodes(head->Right);

    return n1+n2+1;

  }



2.运用递归计算叶子数

代码演示

include<stdio.h>


//先创建二叉树数据对应的结构体
typedef struct BinTree{
  int num;
  struct BinTree*Left;
  struct BinTree*Right;


}Data;


//实现用二叉树计算树的叶子结点数
    int TlNumNodes(Data*head)
  {
    //先设置终止条件
    if (NULL==head)
    {
      return 0;
    }
    else if (head->Left==NULL && head->Right==NULL)
    {
      return 1;
    }
    //现在把普通的情况写出
    n1 =TlNumNodes(head->Left);
    n2 =TlNumNodes(head->Right);

    return n1+n2;

  }include<stdio.h>


//先创建二叉树数据对应的结构体
typedef struct BinTree{
  int num;
  struct BinTree*Left;
  struct BinTree*Right;


}Data;


//实现用二叉树计算树的深度
  int TlNumNodes(Data*head)
  {
    //先设置终止条件
    if (NULL==head)
    {
      return 0;
    }
    //现在把普通的情况写出
    n1 =TlNumNodes(head->Left);
    n2 =TlNumNodes(head->Right);

    return (n1>n2 ? n1:n2)+1;

  }


3.运用递归计算树的深度

代码演示

include<stdio.h>


//先创建二叉树数据对应的结构体
typedef struct BinTree{
  int num;
  struct BinTree*Left;
  struct BinTree*Right;


}Data;


//实现用二叉树计算树的深度
  int TlNumNodes(Data*head)
  {
    //先设置终止条件
    if (NULL==head)
    {
      return 0;
    }
    //现在把普通的情况写出
    n1 =TlNumNodes(head->Left);
    n2 =TlNumNodes(head->Right);

    return (n1>n2 ? n1:n2)+1;

  }



posted @ 2026-09-21 22:37  KunSC  阅读(13)  评论(0)    收藏  举报