1
0
mirror of https://github.com/142vip/408CSFamily.git synced 2026-04-13 18:00:58 +08:00

feat(数据结构): 新增不同语言的查找算法代码

This commit is contained in:
142vip.cn
2023-11-19 23:39:36 +08:00
parent 25013ce9cd
commit ec1dba661f
40 changed files with 1660 additions and 23 deletions

View File

@@ -0,0 +1,35 @@
// 折半查找
void BinaryInsertSort(ElemType Arr[],int n){
int i,j,lowIndex,highIndex,midIndex;
for(i=2;j<=n;i++){
// 将待排序的元素暂存在Arr[0]上
Arr[0]=Arr[i];
lowIndex=1; // 左侧子表 折半查找起始位置
highIndex=i-1; // 左侧子表 折半查找结束位置
while(lowIndex<=highIndex){
// 左侧有序子表的中间位置角标
midIndex=(lowIndex+heightIndex)/2;
if(Arr[midIndex].key>Arr[0].key){
// 小于中间元素,插入位置在子表左侧
highIndex=mid-1
}else{
// 大于或者等于中间元素,插入位置在子表右侧
lowIndex=midIndex+1;
}
}
// 跳出循环需要lowIndex>heightIndex
// 说明待插入位置的角标在heightIndex之后为 heightIndex+1,此时需要将heightIndexi之间的所有元素后移
for(j=i-1;j>highIndex;--j){
Arr[j+1]=Arr[j]
}
// 后移完成后将元素Arr[0]赋值到位置highIndex+1
Arr[highIndex+1]=Arr[0]
}
}

View File

@@ -0,0 +1,43 @@
// 冒泡排序
void BubbleSwapSort(ElemType A[], int n){
for(i=0;i<n-1;i++){
// 当前趟次冒泡是否发生了元素交换初始化为false
bool flag=false;
for(j=n-1;j>i;j--){
if(A[j-1].key>A[j].key){
// 将两个元素A[j-1]、A[j]进行交换,有多种方法
swap(A[j-1],A[j])
// 确认已发生交换
flag=true
}
}
// 本趟遍历后没有发生交换,说明表已经有序
if(flag==false){
return ;
}
}
}
/**
* 加减法实现两个元素值互换
*/
void swap(int a, int b){
// 此时a为两值的和
a=a+b;
// 此时b的值为a
b=a-b
// 如何实现让a的值为b呢此时a的值为b
a=a-b;
}
// 临时变量实现两个元素值的互换
void swap(int a,int b){
int temp;
temp=a;
a=b;
b=temp
}

View File

@@ -0,0 +1,115 @@
// 单链表头插法
LinkList CreateListWithStartNode(LinkList &L){
LNode *s;
int x;
L=(LinkList)malloc(sizeof(LNode)); // 创建头结点L
L->next=NULL; // 初始化空链表
// 控制台输入值
scanf("%d",&x);
// 输入9999 表示结束
while(x!==9999){
// 开辟新结点存储空间
s=(LNode*)malloc(sizeof(LNode));
// 结点数据域赋值
s->data=x;
// 修改指针新结点插入表中【注意L->next为头结点的指针域】
s->next=L->next;
L->next=s;
scanf("%d",&x);
}
// 返回单链表
return L;
}
// 单链表尾插法
LinkList CreateListWithEndNode(LinkList &L){
int x; // 输入结点值
L=(LinkList)malloc(sizeof(LNode));
LNode *s; // 新结点s
LNode *r=L; // r为尾指针
// 控制台输入值
scanf("%d",&x);
while(x!==9999){
// 开辟新结点存储空间
s=(LNode *)malloc(sizeof(LNode));
// 新结点s的数据域赋值为x
s->data=x;
// 单链表L的尾指针指向新的结点s
r->next=s;
// 指针r指向新的表尾结点
r=s;
scanf("%d",&x);
}
// 表尾指针置空【重要】
r->next=NULL;
// 返回单链表
return L;
}
// 单链表按序号查找
LNode *GetElem(LinkList L,int i){
int j=1; // 查询计数初始为1
LNode *p=L->next; // 单链表头结点指针赋值给指针p
// 第0个元素则指向头结点返回头结点
if(i==0){
// 头结点包含数据域和指针域
return L;
}
// 不等于0却小于1则i为负数无效直接返回NULL查询结果空
if(i<1){
return NULL;
}
// p存在且计数没有走到初始i的位置
while(p&&j<i){
// 指针后移
p=p->next;
// 计数标记+1
j++;
}
// 注意: 当p不存在时 跳出循环p=NULL; 当p存在但是j大于等于i跳出循环返回查找的结果返回p
// 从跳出循环上来分析p要么存在即找到的结点元素要么为空即NULL
// 跳出循环返回第i个结点的指针
return p;
}
//单链表按值查找
LNode *LocateElem(LinkList L,ElemType e){
// 指针【哨兵】
LNode *p=L->next;
// 从第1个结点开始查找数据域(data)为e的结点
while(p!=NULL&&p->data!=e){
// 无法匹配,指针后移
p=p->next;
}
// 注意p为NULL的时候说明单链表已经遍历的尾结点了跳出循环没有找到目标结点
// 查找到第1个匹配的结点跳出循环返回结点指针
return p;
//
}

View File

@@ -0,0 +1,69 @@
// 链栈类型定义【基础】
typedef struct LinkNode{
ElemType data; // 栈元素结点数据域
struct LinkNode *next; // 栈元素结点指针域
} *LinkStack;
// 更为详细的定义
typedef struct StackNode
{
int data;//结点数据域
struct StackNode* next;//结点指针域
}StackNode,* LinkTop;
//链栈的数据结构
typedef struct LinkStack
{
LinkTop top; //栈顶结点,定义了一个指向上个结构体的指针
int count;//元素个数
}LinkStack;
// 基于单链表链栈的进栈操作
bool linkStackPushNode(LinkStack* linkStack,int e){
// 判断链栈是否存在
if (!linkStack){
//链栈不存在无法进栈操作返回false
return false;
}
// 开辟栈结点元素内存控件
StackNode* node = (StackNode*)malloc(sizeof(StackNode));
// 新结点指针域指向链表,即栈顶指针位置,元素加入链表
node->next = linkStack->top;
// 新结点数据域赋值
node->data = e;
// 元素进栈,移动栈顶指针,指向新入栈的元素
linkStack->top = node;
// 链栈元素总数+1
linkStack->count++;
//链栈入栈成功返回true
return true;
}
/*
* 基于单链表链栈的出栈操作
*
*/
bool linkStackPopNode(LinkStack* linkStack,int *e){
// 判断链栈是否存在及是否为空
if (!linkStack || linkStack->count==0){
//出栈失败返回false
return false;
}
// 获取栈顶元素结点
StackNode* node = stack->top;
// 结点元素数据域赋值给变量e
*e = linkStack->data;
// 移动栈顶指向,栈顶指针指向待出栈结点的后继结点
linkStack->top = node->next;
// 变量e已被赋值释放链栈出栈元素的内存控件
free(node);
// 链栈元素个数-1
linkStack->count--;
// 出栈成功返回true.
return true;
}

View File

@@ -0,0 +1,42 @@
// 队列最大存储元素个数
#define MaxSize 50
// 结构体定义
typedef struct {
// 存放队列元素
ElemType data[MaxSize];
// 队头指针和队尾指针
int front,rear;
} SqQueue;
// 入队算法
// 尾插法Q.data[Q.rear]=x;Q.rear=(Q.rear+1)%Maxsize;Q.tag=1
// 队空条件Q.front== Q.rear且Q.tag==0
int EnLoopQueue(SqQueue &Q, ElemType x){
if(Q.front==Q.rear&&Q.tag==1){
return 0;
}
Q.data[Q.rear]=x;
Q.rear=(Q.rear+1)%MaxSize;
Q.tag=1;
return 1;
}
// 出队算法
// 头结点删除x=Q.data[Q.front];Q.front=(Q.front +1)%Maxsize;Q.tag=0
// 队满条件Q.front == Q.rear且Q.tag=1
// 注意:当删除之后链表为空时,还需增加一步,将尾指针指向头结点
int DeLoopQueue(SqQueue &Q, ElemType &x){
if (Q.front==Q.rear&&Q.tag==0){
return 0;
}
x=Q.data[Q.front];
Q.front=(Q.front+1)%MaxSize;
Q.tag=0;
return 1;
}

View File

@@ -0,0 +1,35 @@
// 快速排序【伪代码】
void QuickSort(ElemType A[] , int low , int high){
// low > high 表角标越界low=high 子表只有一个元素,不需要进行快排,已经有序
if(low<high){
// 获取pivot基准将当前待排序表分成左右两个子表
int pivotKey = Partition(A,low,high)
// 对左边序列进行快排
QuickSort(A,low,pivotKey-1)
// 对右边序列进行快排
QuickSort(A,pivotKey+1,high)
}
return A
}
int Partition(ElemType A ,int low , int high){
ElemType pivot=A[low];
while(low<high){
while(low<high && A[high]>=pivot) --high
A[low]=A[high] // 比pivot小的都移到左表 注意--high 从后往前遍历
while(low<high && A[low]<=pivot ) ++low
A[high]=A[low] // 比pivot大的都移到右表注意++low 从前往后遍历
}
// 此时low==high||low>high 跳出循环后即找到能将当前表一分为二的pivotKey值
A[low]=pivot
// 基准元素pivot对应最终的位置角标
return low
}

View File

@@ -0,0 +1,48 @@
// 希尔排序【伪代码】
void ShellSort(ElemType Arr[] , int n){
// k是增量
for(k=n/2;k>=1;k=k/2){
// 增量子表进行直接插入排序
for(i=k+1;i<=n;++i){
if(Arr[i].key<Arr[i-k].key){
// 元素暂存
Arr[0]=Arr[i];
for(j=i-k;j>0&&Arr[0].key<Arr[j].key;j-=k){
// 记录后移,查找插入的位置
Arr[j+k]=Arr[j]
}
// 插入
Arr[j+k]=Arr[0]
}
}
}
}
void ShellSortEnhance(ElemType Arr[] , int n){
// 采用k=n/2 幂函数 确认希尔排序的步长
for(k=n/2;k>=1;n/=2){
// // 步长为k则对应分为k个组分别对其进行 直接插入排序
for(i=1,i<=k;i++){
// 第一步: 对应组的元素找出来,组成新的待排序的数列
// 第二步: 对待排序数列进行 直接插入排序
specialStraightInsertSort(ElemType Arr[], int n , int k , int i)
}
}
// 返回
return Arr;
}

View File

@@ -0,0 +1,70 @@
// 顺序表的基础操作
// 基础结构体
define MaxSize 50;
typedef struct{
ElemType data[MaxSize]; // ElemType 代表元素类型 int、string.....
int length;
}SqList
bool ListInsert(SqList &L, int i, ElemType e){
// i非法 i=1 表头 i=L.length+1 表尾巴
if(i<1||i>L.length+1){
return false;
}
// 存储空间满,无法插入
if(L.length >= MaxSize){
return false;
}
// 遍历,将位置元素往后移动,注意从后往前循环,避免值被覆盖
for(int j=L.length; j>=i;j--){
L.data[j]=L.data[j-1];
}
// 此时表L中的第i个元素和第i+1元素素值一样将新元素存入i位置即可
// 第i个元素对应的位置角标为i-1
L.data[i-1]=e;
// 表长度加1
L.length++;
// 返回插入成功
return true;
}
bool ListDelete(SqList &L, int i, ElemType &e){
// i非法 i=1 表头 i=L.length+1 表尾巴
if(i<1||i>L.length+1){
return false;
}
// 存储空间满,无法插入
if(L.length >= MaxSize){
return false;
}
// 引用变量e赋值
e=L.data[i-1]
// 遍历第i个元素后面的往前移动
for(int j=i; j<=L.length;j++){
// 从第i个元素开始角标从i-1开始
L.data[j-1]=L.data[j];
}
// 此时表L中的表尾元素和倒数第二个元素值一样将表的长度-1
// 表长度减1
L.length--;
// 返回删除成功
return true;
}

View File

@@ -0,0 +1,71 @@
// 定义栈中元素的最大个数
# define MaxSize 50
// 结构体定义
typedef struct{
ElemType data[MaxSize]; // 存放栈中元素
int top; // 栈顶指针
}SqStack;
// 初始化
void InitStack(&S){
// 栈顶指针-1
s.top=-1;
}
// 栈空判断
bool StackEmpty(S){
if(S.top==-1){
// 栈空
return true;
}else{
// 栈非空
return false;
}
}
// 进栈
bool Push(SqStack &S,ElemType x){
if(S.top==MaxSize-1){
// 栈满返回false元素无法进行进栈操作
return false;
}else{
// 可进栈,栈顶指针+1再元素入栈
S.data[++S.top]=x;
// 入栈成功
return true;
}
}
// 出栈
bool Pop(SqStack &S,ElemType &x){
if(S.top==-1){
// 栈空无栈顶元素可出栈返回false
return false;
}else{
// 栈非空,先元素出栈,再进行指针-1
x=S.data[S.top--];
// 出栈成功返回true
return true;
}
}
// 读(获取)栈顶元素
bool GetTop(SqStack S,ElemType &x){
if(S.top==-1){
// 栈空,无栈顶元素,返回false
return false;
}else{
// 通过栈顶指针获取栈顶元素赋值给变量x
x=S.data[S.top];
// 读取栈顶元素成功返回true
return true;
}
}

View File

@@ -0,0 +1,19 @@
// 直接插入排序【伪代码】
void straightInsertSort(ElemType A[], int n){
int i,j;
// 依次将前面的第2到第n个元素插入到前面的有序序列
for(i=2;i<=n;i++){
if(A[i].key< A[i-1].key){
// 哨兵元素
A[0]=A[i];
// 循环向后挪动
for(j=i-1;A[0].key<A[j].key;--j){
A[j+1]=A[j]
}
// 哨兵元素插入注意这里为j+1因为--j等循环完先递减再使用比预想靠后
A[j+1]=A[0]
}
}
}

View File

@@ -0,0 +1,35 @@
// 折半查找
void BinaryInsertSort(ElemType Arr[],int n){
int i,j,lowIndex,highIndex,midIndex;
for(i=2;j<=n;i++){
// 将待排序的元素暂存在Arr[0]上
Arr[0]=Arr[i];
lowIndex=1; // 左侧子表 折半查找起始位置
highIndex=i-1; // 左侧子表 折半查找结束位置
while(lowIndex<=highIndex){
// 左侧有序子表的中间位置角标
midIndex=(lowIndex+heightIndex)/2;
if(Arr[midIndex].key>Arr[0].key){
// 小于中间元素,插入位置在子表左侧
highIndex=mid-1
}else{
// 大于或者等于中间元素,插入位置在子表右侧
lowIndex=midIndex+1;
}
}
// 跳出循环需要lowIndex>heightIndex
// 说明待插入位置的角标在heightIndex之后为 heightIndex+1,此时需要将heightIndexi之间的所有元素后移
for(j=i-1;j>highIndex;--j){
Arr[j+1]=Arr[j]
}
// 后移完成后将元素Arr[0]赋值到位置highIndex+1
Arr[highIndex+1]=Arr[0]
}
}

View File

@@ -0,0 +1,43 @@
// 冒泡排序
void BubbleSwapSort(ElemType A[], int n){
for(i=0;i<n-1;i++){
// 当前趟次冒泡是否发生了元素交换初始化为false
bool flag=false;
for(j=n-1;j>i;j--){
if(A[j-1].key>A[j].key){
// 将两个元素A[j-1]、A[j]进行交换,有多种方法
swap(A[j-1],A[j])
// 确认已发生交换
flag=true
}
}
// 本趟遍历后没有发生交换,说明表已经有序
if(flag==false){
return ;
}
}
}
/**
* 加减法实现两个元素值互换
*/
void swap(int a, int b){
// 此时a为两值的和
a=a+b;
// 此时b的值为a
b=a-b
// 如何实现让a的值为b呢此时a的值为b
a=a-b;
}
// 临时变量实现两个元素值的互换
void swap(int a,int b){
int temp;
temp=a;
a=b;
b=temp
}

View File

@@ -0,0 +1,115 @@
// 单链表头插法
LinkList CreateListWithStartNode(LinkList &L){
LNode *s;
int x;
L=(LinkList)malloc(sizeof(LNode)); // 创建头结点L
L->next=NULL; // 初始化空链表
// 控制台输入值
scanf("%d",&x);
// 输入9999 表示结束
while(x!==9999){
// 开辟新结点存储空间
s=(LNode*)malloc(sizeof(LNode));
// 结点数据域赋值
s->data=x;
// 修改指针新结点插入表中【注意L->next为头结点的指针域】
s->next=L->next;
L->next=s;
scanf("%d",&x);
}
// 返回单链表
return L;
}
// 单链表尾插法
LinkList CreateListWithEndNode(LinkList &L){
int x; // 输入结点值
L=(LinkList)malloc(sizeof(LNode));
LNode *s; // 新结点s
LNode *r=L; // r为尾指针
// 控制台输入值
scanf("%d",&x);
while(x!==9999){
// 开辟新结点存储空间
s=(LNode *)malloc(sizeof(LNode));
// 新结点s的数据域赋值为x
s->data=x;
// 单链表L的尾指针指向新的结点s
r->next=s;
// 指针r指向新的表尾结点
r=s;
scanf("%d",&x);
}
// 表尾指针置空【重要】
r->next=NULL;
// 返回单链表
return L;
}
// 单链表按序号查找
LNode *GetElem(LinkList L,int i){
int j=1; // 查询计数初始为1
LNode *p=L->next; // 单链表头结点指针赋值给指针p
// 第0个元素则指向头结点返回头结点
if(i==0){
// 头结点包含数据域和指针域
return L;
}
// 不等于0却小于1则i为负数无效直接返回NULL查询结果空
if(i<1){
return NULL;
}
// p存在且计数没有走到初始i的位置
while(p&&j<i){
// 指针后移
p=p->next;
// 计数标记+1
j++;
}
// 注意: 当p不存在时 跳出循环p=NULL; 当p存在但是j大于等于i跳出循环返回查找的结果返回p
// 从跳出循环上来分析p要么存在即找到的结点元素要么为空即NULL
// 跳出循环返回第i个结点的指针
return p;
}
//单链表按值查找
LNode *LocateElem(LinkList L,ElemType e){
// 指针【哨兵】
LNode *p=L->next;
// 从第1个结点开始查找数据域(data)为e的结点
while(p!=NULL&&p->data!=e){
// 无法匹配,指针后移
p=p->next;
}
// 注意p为NULL的时候说明单链表已经遍历的尾结点了跳出循环没有找到目标结点
// 查找到第1个匹配的结点跳出循环返回结点指针
return p;
//
}

View File

@@ -0,0 +1,69 @@
// 链栈类型定义【基础】
typedef struct LinkNode{
ElemType data; // 栈元素结点数据域
struct LinkNode *next; // 栈元素结点指针域
} *LinkStack;
// 更为详细的定义
typedef struct StackNode
{
int data;//结点数据域
struct StackNode* next;//结点指针域
}StackNode,* LinkTop;
//链栈的数据结构
typedef struct LinkStack
{
LinkTop top; //栈顶结点,定义了一个指向上个结构体的指针
int count;//元素个数
}LinkStack;
// 基于单链表链栈的进栈操作
bool linkStackPushNode(LinkStack* linkStack,int e){
// 判断链栈是否存在
if (!linkStack){
//链栈不存在无法进栈操作返回false
return false;
}
// 开辟栈结点元素内存控件
StackNode* node = (StackNode*)malloc(sizeof(StackNode));
// 新结点指针域指向链表,即栈顶指针位置,元素加入链表
node->next = linkStack->top;
// 新结点数据域赋值
node->data = e;
// 元素进栈,移动栈顶指针,指向新入栈的元素
linkStack->top = node;
// 链栈元素总数+1
linkStack->count++;
//链栈入栈成功返回true
return true;
}
/*
* 基于单链表链栈的出栈操作
*
*/
bool linkStackPopNode(LinkStack* linkStack,int *e){
// 判断链栈是否存在及是否为空
if (!linkStack || linkStack->count==0){
//出栈失败返回false
return false;
}
// 获取栈顶元素结点
StackNode* node = stack->top;
// 结点元素数据域赋值给变量e
*e = linkStack->data;
// 移动栈顶指向,栈顶指针指向待出栈结点的后继结点
linkStack->top = node->next;
// 变量e已被赋值释放链栈出栈元素的内存控件
free(node);
// 链栈元素个数-1
linkStack->count--;
// 出栈成功返回true.
return true;
}

View File

@@ -0,0 +1,42 @@
// 队列最大存储元素个数
#define MaxSize 50
// 结构体定义
typedef struct {
// 存放队列元素
ElemType data[MaxSize];
// 队头指针和队尾指针
int front,rear;
} SqQueue;
// 入队算法
// 尾插法Q.data[Q.rear]=x;Q.rear=(Q.rear+1)%Maxsize;Q.tag=1
// 队空条件Q.front== Q.rear且Q.tag==0
int EnLoopQueue(SqQueue &Q, ElemType x){
if(Q.front==Q.rear&&Q.tag==1){
return 0;
}
Q.data[Q.rear]=x;
Q.rear=(Q.rear+1)%MaxSize;
Q.tag=1;
return 1;
}
// 出队算法
// 头结点删除x=Q.data[Q.front];Q.front=(Q.front +1)%Maxsize;Q.tag=0
// 队满条件Q.front == Q.rear且Q.tag=1
// 注意:当删除之后链表为空时,还需增加一步,将尾指针指向头结点
int DeLoopQueue(SqQueue &Q, ElemType &x){
if (Q.front==Q.rear&&Q.tag==0){
return 0;
}
x=Q.data[Q.front];
Q.front=(Q.front+1)%MaxSize;
Q.tag=0;
return 1;
}

View File

@@ -0,0 +1,35 @@
// 快速排序【伪代码】
void QuickSort(ElemType A[] , int low , int high){
// low > high 表角标越界low=high 子表只有一个元素,不需要进行快排,已经有序
if(low<high){
// 获取pivot基准将当前待排序表分成左右两个子表
int pivotKey = Partition(A,low,high)
// 对左边序列进行快排
QuickSort(A,low,pivotKey-1)
// 对右边序列进行快排
QuickSort(A,pivotKey+1,high)
}
return A
}
int Partition(ElemType A ,int low , int high){
ElemType pivot=A[low];
while(low<high){
while(low<high && A[high]>=pivot) --high
A[low]=A[high] // 比pivot小的都移到左表 注意--high 从后往前遍历
while(low<high && A[low]<=pivot ) ++low
A[high]=A[low] // 比pivot大的都移到右表注意++low 从前往后遍历
}
// 此时low==high||low>high 跳出循环后即找到能将当前表一分为二的pivotKey值
A[low]=pivot
// 基准元素pivot对应最终的位置角标
return low
}

View File

@@ -0,0 +1,48 @@
// 希尔排序【伪代码】
void ShellSort(ElemType Arr[] , int n){
// k是增量
for(k=n/2;k>=1;k=k/2){
// 增量子表进行直接插入排序
for(i=k+1;i<=n;++i){
if(Arr[i].key<Arr[i-k].key){
// 元素暂存
Arr[0]=Arr[i];
for(j=i-k;j>0&&Arr[0].key<Arr[j].key;j-=k){
// 记录后移,查找插入的位置
Arr[j+k]=Arr[j]
}
// 插入
Arr[j+k]=Arr[0]
}
}
}
}
void ShellSortEnhance(ElemType Arr[] , int n){
// 采用k=n/2 幂函数 确认希尔排序的步长
for(k=n/2;k>=1;n/=2){
// // 步长为k则对应分为k个组分别对其进行 直接插入排序
for(i=1,i<=k;i++){
// 第一步: 对应组的元素找出来,组成新的待排序的数列
// 第二步: 对待排序数列进行 直接插入排序
specialStraightInsertSort(ElemType Arr[], int n , int k , int i)
}
}
// 返回
return Arr;
}

View File

@@ -0,0 +1,70 @@
// 顺序表的基础操作
// 基础结构体
define MaxSize 50;
typedef struct{
ElemType data[MaxSize]; // ElemType 代表元素类型 int、string.....
int length;
}SqList
bool ListInsert(SqList &L, int i, ElemType e){
// i非法 i=1 表头 i=L.length+1 表尾巴
if(i<1||i>L.length+1){
return false;
}
// 存储空间满,无法插入
if(L.length >= MaxSize){
return false;
}
// 遍历,将位置元素往后移动,注意从后往前循环,避免值被覆盖
for(int j=L.length; j>=i;j--){
L.data[j]=L.data[j-1];
}
// 此时表L中的第i个元素和第i+1元素素值一样将新元素存入i位置即可
// 第i个元素对应的位置角标为i-1
L.data[i-1]=e;
// 表长度加1
L.length++;
// 返回插入成功
return true;
}
bool ListDelete(SqList &L, int i, ElemType &e){
// i非法 i=1 表头 i=L.length+1 表尾巴
if(i<1||i>L.length+1){
return false;
}
// 存储空间满,无法插入
if(L.length >= MaxSize){
return false;
}
// 引用变量e赋值
e=L.data[i-1]
// 遍历第i个元素后面的往前移动
for(int j=i; j<=L.length;j++){
// 从第i个元素开始角标从i-1开始
L.data[j-1]=L.data[j];
}
// 此时表L中的表尾元素和倒数第二个元素值一样将表的长度-1
// 表长度减1
L.length--;
// 返回删除成功
return true;
}

View File

@@ -0,0 +1,71 @@
// 定义栈中元素的最大个数
# define MaxSize 50
// 结构体定义
typedef struct{
ElemType data[MaxSize]; // 存放栈中元素
int top; // 栈顶指针
}SqStack;
// 初始化
void InitStack(&S){
// 栈顶指针-1
s.top=-1;
}
// 栈空判断
bool StackEmpty(S){
if(S.top==-1){
// 栈空
return true;
}else{
// 栈非空
return false;
}
}
// 进栈
bool Push(SqStack &S,ElemType x){
if(S.top==MaxSize-1){
// 栈满返回false元素无法进行进栈操作
return false;
}else{
// 可进栈,栈顶指针+1再元素入栈
S.data[++S.top]=x;
// 入栈成功
return true;
}
}
// 出栈
bool Pop(SqStack &S,ElemType &x){
if(S.top==-1){
// 栈空无栈顶元素可出栈返回false
return false;
}else{
// 栈非空,先元素出栈,再进行指针-1
x=S.data[S.top--];
// 出栈成功返回true
return true;
}
}
// 读(获取)栈顶元素
bool GetTop(SqStack S,ElemType &x){
if(S.top==-1){
// 栈空,无栈顶元素,返回false
return false;
}else{
// 通过栈顶指针获取栈顶元素赋值给变量x
x=S.data[S.top];
// 读取栈顶元素成功返回true
return true;
}
}

View File

@@ -0,0 +1,19 @@
// 直接插入排序【伪代码】
void straightInsertSort(ElemType A[], int n){
int i,j;
// 依次将前面的第2到第n个元素插入到前面的有序序列
for(i=2;i<=n;i++){
if(A[i].key< A[i-1].key){
// 哨兵元素
A[0]=A[i];
// 循环向后挪动
for(j=i-1;A[0].key<A[j].key;--j){
A[j+1]=A[j]
}
// 哨兵元素插入注意这里为j+1因为--j等循环完先递减再使用比预想靠后
A[j+1]=A[0]
}
}
}

View File

@@ -0,0 +1,44 @@
/**
* 折半插入排序【JavaScript版本】
*/
function binaryInsertSort(arr, len) {
// 数组长度校验【非必须】
len = arr.length === len
? len
: arr.length
// 遍历
for (let i = 1; i < len; i++) {
const temp = arr[i]
let lowIndex = 0
let highIndex = i - 1
while (lowIndex <= highIndex) {
// 注意:取整,javascript这里取整会出现空指针
const mid = Math.ceil((lowIndex + highIndex) / 2)
if (arr[mid] <= temp) {
// 右侧
lowIndex = mid + 1
} else {
// 左侧
highIndex = mid - 1
}
}
// 元素后移
for (let j = i - 1; j > highIndex; --j) {
arr[j + 1] = arr[j]
}
arr[highIndex + 1] = temp
}
// 返回经过折半插入排序处理的有序数组
return arr
}
// 测试用例
const dealArr = [5, 2, 7, 3, 18, 8, 12, 1]
console.log('插入排序前:', dealArr)
const sortResult = binaryInsertSort(dealArr, 7)
console.log('插入排序后:', sortResult)

View File

@@ -0,0 +1,37 @@
/**
* 冒泡排序【JavaScript版本】
*/
function BubbleSort(arr, len) {
// 校正数组的长度
len = arr.length === len ? len : arr.length
// 冒泡排序让数组arr有序
for (let i = 0; i < len - 1; i++) {
let isSorted = false
// len个数组进行len-1趟一趟冒泡
for (let j = len - 1; j > i; j--) {
// 注意这里的for循环倒序是有讲究的想象一下泡泡不都是网上升的么....
if (arr[j - 1] > arr[j]) {
// 交换元素,始终让最小的元素往上走(冒泡)
const temp = arr[j - 1]
arr[j - 1] = arr[j]
arr[j] = temp
// 需要冒泡
isSorted = true
}
}
// 第一趟比较后,如果本身序列是有序的,就直接跳出循环
if (isSorted === false) {
break
}
}
return arr
}
const initArr = [1, 5, 8, 3, 2, 9, 16]
console.log(`冒泡排序前:${initArr}`)
const sortedArr = BubbleSort(initArr, 7)
console.log(`冒泡排序后:${sortedArr}`)

View File

@@ -0,0 +1,54 @@
/**
* 基于分治法思想,将数组进行快速排序
* @param {Array} arr 待排序的数组
* @param {int} low 数组低位角标 左指针
* @param {int} high 数组高位角标 右指针
*/
function QuickSort(arr, low, high) {
// low=high 说明只有一个元素,理解为有序,不做处理
// low>high 说明左、右指针已经重合,数组已经遍历完,需要跳出
if (low < high) {
const pivotIndex = Partition(arr, low, high)
// 处理左侧
QuickSort(arr, low, pivotIndex - 1)
// 处理右侧
QuickSort(arr, pivotIndex + 1, high)
}
// 经过快排处理的数组
return arr
}
/**
*
* 寻找数组中的基准pivot使得左侧元素全部小于等于pivot右侧元素全部大于等于pivot
* @param {Array} arr 分治思想处理后的数组
* @param {int} low 数组低位角标 左指针
* @param {int} high 数组高位角标 右指针
*/
function Partition(arr, low, high) {
// 假设低位指针对应数组角标元素为基准pivot
const pivot = arr[low]
while (low < high) {
// 从右往左直到比pivot小跳出循环
while (low < high && arr[high] >= pivot) --high
arr[low] = arr[high]
// 从左往右直到比pivot大跳出循环
while (low < high && arr[low] <= pivot) ++low
arr[high] = arr[low]
}
// 基准值移到最终的位置此时左侧小于等于pivot 右侧大于等于pivot
arr[low] = pivot
// 返回基准值的角标
return low
}
const initArr = [2, 18, 6, 25, 19, 4, 8, 3, 7]
console.log(`快速排序处理前:${initArr}`)
const quickSortResult = QuickSort(initArr, 0, 8)
console.log(`快速排序处理后:${quickSortResult}`)

View File

@@ -0,0 +1,83 @@
/**
* 数组的希尔排序
* - 返回已排序的数组,从小到大
* @param {Array} arr 待排序数组
* @param {int} len 数组长度,可校验
* @returns
*/
function shellSort(arr, len) {
// 校对数组长度
len = arr.length === len ? len : arr.length
// 注意处理浮点【向上取整】 防止空指针
for (let increment = Math.floor(len / 2); increment >= 1; increment = Math.floor(increment / 2)) {
// 对每组数据,进行直接排序
for (let groupIndex = 0; groupIndex < increment; ++groupIndex) {
specialStraightInsertSort(arr, len, increment, groupIndex)
}
}
return arr
}
/**
* 根据希尔排序的步长对分组进行直接插入排序处理
* @param {Array} arr 排序数组
* @param {int} len 数组长度
* @param {int} increment 增量步长
* @param {int} groupIndex 分组,第几个分组
*/
function specialStraightInsertSort(arr, len, increment, groupIndex) {
len = arr.length === len ? len : arr.length
console.log(`数组长度:${len}----->当前步长:${increment}---->分组:${groupIndex}`)
for (let eleStartIndex = groupIndex + increment; eleStartIndex < len; eleStartIndex += increment) {
// 此时eleStartIndex为直接插入排序的比较元素
// 直接插入排序中的哨兵元素【重要】
const temp = arr[eleStartIndex]
let j
// 向前比较 从小到大
for (j = eleStartIndex - increment; j >= 0 && arr[j] > temp; j -= increment) {
arr[j + increment] = arr[j]
}
arr[j + increment] = temp
}
console.log('specialStraightInsertSort处理后', arr)
return arr
}
const dealArr = [5, 8, 2, 16, 3, 9, 1]
console.log('插入排序前:', dealArr)
const sortResult = shellSort(dealArr, 7)
console.log('插入排序后:', sortResult)
/**
* 简化的希尔排序
* - 返回已排序号的数组,从小到大
* @param {Array} arr
*/
function shellSortBetter(arr) {
const len = arr.length
let increment = Math.floor(len / 2)
while (increment !== 0) {
for (let i = increment; i < len; i++) {
const temp = arr[i]
for (let j = i - increment; j >= 0 && temp < arr[j]; j -= increment) {
arr[j + increment] = arr[j]
}
arr[i + increment] = temp
}
increment = Math.floor(increment / 2)
}
return arr
}
console.log('简化shellSortBetter希尔排序前', dealArr)
const sortResultBetter = shellSortBetter(dealArr)
console.log('简化shellSortBetter希尔排序后', sortResultBetter)

View File

@@ -0,0 +1,34 @@
/**
* 直接插入排序【JavaScript版本】
*/
function straightInsertSort(arr, len) {
// 重新确定数组长度
len = arr.length === len ? len : arr.length
// 从第二个元素开始循环共len-1次
for (let i = 1; i < len; i++) {
// 后面的额元素比前面的元素小,需要把前面大于哨兵元素有序序列,移动后面一位
if (arr[i] < arr[i - 1]) {
let j
// 哨兵元素
const temp = arr[i]
for (j = i - 1; arr[j] > temp; --j) {
// 后移
arr[j + 1] = arr[j]
}
// 跳出循环逻辑出现arr[j] > arr[j-1]
// 哨兵即待排序的
arr[j + 1] = temp
}
}
return arr
}
const dealArr = [5, 2, 7, 3, 18, 8, 12, 1]
console.log('插入排序前:', dealArr)
const sortResult = straightInsertSort(dealArr, 7)
console.log('插入排序后:', sortResult)

View File

@@ -0,0 +1,44 @@
/**
* 折半插入排序【JavaScript版本】
*/
function binaryInsertSort(arr, len) {
// 数组长度校验【非必须】
len = arr.length === len
? len
: arr.length
// 遍历
for (let i = 1; i < len; i++) {
const temp = arr[i]
let lowIndex = 0
let highIndex = i - 1
while (lowIndex <= highIndex) {
// 注意:取整,javascript这里取整会出现空指针
const mid = Math.ceil((lowIndex + highIndex) / 2)
if (arr[mid] <= temp) {
// 右侧
lowIndex = mid + 1
} else {
// 左侧
highIndex = mid - 1
}
}
// 元素后移
for (let j = i - 1; j > highIndex; --j) {
arr[j + 1] = arr[j]
}
arr[highIndex + 1] = temp
}
// 返回经过折半插入排序处理的有序数组
return arr
}
// 测试用例
const dealArr = [5, 2, 7, 3, 18, 8, 12, 1]
console.log('插入排序前:', dealArr)
const sortResult = binaryInsertSort(dealArr, 7)
console.log('插入排序后:', sortResult)

View File

@@ -0,0 +1,47 @@
/**
* 排序算法:冒泡排序
* 给定一个数组,按照从小到大或从大到小排序,打印排序前后结果对比
* 编程语言TypeScript
*/
function BubbleSort(arr:Array<number>):number[] {
// 获取数组长度
const len = arr.length
// 冒泡排序让数组arr有序
for (let i = 0; i < len - 1; i++) {
let isSorted = false
// len个数组进行len-1趟一趟冒泡
for (let j = len - 1; j > i; j--) {
// 注意这里的for循环倒序是有讲究的想象一下泡泡不都是网上升的么....
if (arr[j - 1] > arr[j]) {
// 交换元素,始终让最小的元素往上走(冒泡)
const temp = arr[j - 1]
arr[j - 1] = arr[j]
arr[j] = temp
// 需要冒泡
isSorted = true
}
}
// 第一趟比较后,如果本身序列是有序的,就直接跳出循环
if (isSorted === false) {
break
}
}
return arr
}
/**
* 将两个变量数值交换
*/
function switchValue(params:{ a: number, b: number }):{a:number, b:number} {
const { a: newB, b: newA } = params
return { a: newA, b: newB }
}
const initArr = [1, 5, 8, 3, 2, 9, 16]
console.log(`冒泡排序前:${initArr}`)
const sortedArr = BubbleSort(initArr)
console.log(`冒泡排序后:${sortedArr}`)

View File

@@ -0,0 +1,54 @@
/**
* 基于分治法思想,将数组进行快速排序
* @param {Array} arr 待排序的数组
* @param {int} low 数组低位角标 左指针
* @param {int} high 数组高位角标 右指针
*/
function QuickSort(arr, low, high) {
// low=high 说明只有一个元素,理解为有序,不做处理
// low>high 说明左、右指针已经重合,数组已经遍历完,需要跳出
if (low < high) {
const pivotIndex = Partition(arr, low, high)
// 处理左侧
QuickSort(arr, low, pivotIndex - 1)
// 处理右侧
QuickSort(arr, pivotIndex + 1, high)
}
// 经过快排处理的数组
return arr
}
/**
*
* 寻找数组中的基准pivot使得左侧元素全部小于等于pivot右侧元素全部大于等于pivot
* @param {Array} arr 分治思想处理后的数组
* @param {int} low 数组低位角标 左指针
* @param {int} high 数组高位角标 右指针
*/
function Partition(arr, low, high) {
// 假设低位指针对应数组角标元素为基准pivot
const pivot = arr[low]
while (low < high) {
// 从右往左直到比pivot小跳出循环
while (low < high && arr[high] >= pivot) --high
arr[low] = arr[high]
// 从左往右直到比pivot大跳出循环
while (low < high && arr[low] <= pivot) ++low
arr[high] = arr[low]
}
// 基准值移到最终的位置此时左侧小于等于pivot 右侧大于等于pivot
arr[low] = pivot
// 返回基准值的角标
return low
}
const initArr = [2, 18, 6, 25, 19, 4, 8, 3, 7]
console.log(`快速排序处理前:${initArr}`)
const quickSortResult = QuickSort(initArr, 0, 8)
console.log(`快速排序处理后:${quickSortResult}`)

View File

@@ -0,0 +1,83 @@
/**
* 数组的希尔排序
* - 返回已排序的数组,从小到大
* @param {Array} arr 待排序数组
* @param {int} len 数组长度,可校验
* @returns
*/
function shellSort(arr, len) {
// 校对数组长度
len = arr.length === len ? len : arr.length
// 注意处理浮点【向上取整】 防止空指针
for (let increment = Math.floor(len / 2); increment >= 1; increment = Math.floor(increment / 2)) {
// 对每组数据,进行直接排序
for (let groupIndex = 0; groupIndex < increment; ++groupIndex) {
specialStraightInsertSort(arr, len, increment, groupIndex)
}
}
return arr
}
/**
* 根据希尔排序的步长对分组进行直接插入排序处理
* @param {Array} arr 排序数组
* @param {int} len 数组长度
* @param {int} increment 增量步长
* @param {int} groupIndex 分组,第几个分组
*/
function specialStraightInsertSort(arr, len, increment, groupIndex) {
len = arr.length === len ? len : arr.length
console.log(`数组长度:${len}----->当前步长:${increment}---->分组:${groupIndex}`)
for (let eleStartIndex = groupIndex + increment; eleStartIndex < len; eleStartIndex += increment) {
// 此时eleStartIndex为直接插入排序的比较元素
// 直接插入排序中的哨兵元素【重要】
const temp = arr[eleStartIndex]
let j
// 向前比较 从小到大
for (j = eleStartIndex - increment; j >= 0 && arr[j] > temp; j -= increment) {
arr[j + increment] = arr[j]
}
arr[j + increment] = temp
}
console.log('specialStraightInsertSort处理后', arr)
return arr
}
const dealArr = [5, 8, 2, 16, 3, 9, 1]
console.log('插入排序前:', dealArr)
const sortResult = shellSort(dealArr, 7)
console.log('插入排序后:', sortResult)
/**
* 简化的希尔排序
* - 返回已排序号的数组,从小到大
* @param {Array} arr
*/
function shellSortBetter(arr) {
const len = arr.length
let increment = Math.floor(len / 2)
while (increment !== 0) {
for (let i = increment; i < len; i++) {
const temp = arr[i]
for (let j = i - increment; j >= 0 && temp < arr[j]; j -= increment) {
arr[j + increment] = arr[j]
}
arr[i + increment] = temp
}
increment = Math.floor(increment / 2)
}
return arr
}
console.log('简化shellSortBetter希尔排序前', dealArr)
const sortResultBetter = shellSortBetter(dealArr)
console.log('简化shellSortBetter希尔排序后', sortResultBetter)

View File

@@ -0,0 +1,34 @@
/**
* 直接插入排序【JavaScript版本】
*/
function straightInsertSort(arr, len) {
// 重新确定数组长度
len = arr.length === len ? len : arr.length
// 从第二个元素开始循环共len-1次
for (let i = 1; i < len; i++) {
// 后面的额元素比前面的元素小,需要把前面大于哨兵元素有序序列,移动后面一位
if (arr[i] < arr[i - 1]) {
let j
// 哨兵元素
const temp = arr[i]
for (j = i - 1; arr[j] > temp; --j) {
// 后移
arr[j + 1] = arr[j]
}
// 跳出循环逻辑出现arr[j] > arr[j-1]
// 哨兵即待排序的
arr[j + 1] = temp
}
}
return arr
}
const dealArr = [5, 2, 7, 3, 18, 8, 12, 1]
console.log('插入排序前:', dealArr)
const sortResult = straightInsertSort(dealArr, 7)
console.log('插入排序后:', sortResult)