Record study record life
数据结构
数据结构

数据结构

文章目录

概念定义

  • :即字符串(String)是由零个或多个字符组成的有限序列

  • 串的长度:串中字符的个数 n,n=0 时的串称为空串

  • 子串:串中任意个连续的字符组成的子序列

  • 主串:包含子串的串。

  • 字符在主串中的位置:字符在串中的序号。(注意:空格也是一个字符

  • 子串在主串中的位置:子串的第一个字符在主串中的位置 。

串的基本操作

  1. StrAssign(&T, chars):赋值操作。把串 T 赋值为 chars。

  2. StrCopy(&T, S):复制操作。由串 S 复制得到串 T。

  3. StrEmpty(S):判空操作。若 S 为空串,则返回 TRUE,否则返回 FALSE。

  4. StrLength(S):求串长。返回串 S 中元素的个数。

  5. ClearString(&S):清空操作。将 S 清为空串。

  6. DestroyString(&S):销毁串。将串 S 销毁(回收存储空间)。

  7. Concat(&T, S1, S2):串联接。用 T 返回由 S1 和 S2 联接而成的新串 。

  8. SubString(&Sub, S, pos, len):求子串。用 Sub 返回串 S 的第 pos 个字符起长度为 len 的子串。

  9. Index(S, T):定位操作。若主串 S 中存在与串 T 值相同的子串,则返回它在主串 S 中第一次出现的位置;否则函数值为 0。

  10. StrCompare(S, T):比较操作。若 S>T,则返回值>0;若 S=T,则返回值=0;若 S<T,则返回值<0。

  • strcpy(s1, s2); 复制字符串 s2 到字符串 s1。

  • strcat(s1, s2); 连接字符串 s2 到字符串 s1 的末尾。

  • strlen(s1);返回字符串 s1 的长度。

  • strcmp(s1, s2);如果 s1 和 s2 是相同的,则返回 0;如果 s1<s2 则返回小于 0;如果 s1>s2 则返回大于 0。

  • strchr(s1, ch);返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。

  • strstr(s1, s2);返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置。

  • strlwr(s1);返回原字符串的小写形式。

  • strupr(s1);返回原字符串的大写形式。

KMP

i不变,j变到第几位就是next数组

改进后判断next的那个与当前是否相同,不同则匹配失败为1

树的属性和性质

属性

结点的度:有几个孩子(分支)

树的度:各结点的度的最大值

性质

1)结点数=总度数+1

2)度为m的树、m叉树的区别 度为m的树: ① 任意结点的度<=m(最多m个孩子) ② 至少有一个结点度=m(有m个孩子) ③ 一定是非空树,至少有m+1个结点

m叉树: ① 任意结点的度<=m(最多m个孩子) ② 允许所有结点的度都<m ③ 可以是空树

3)度为m的树第 i 层至多有m^(i-1)个结点(i>=1) m叉树第 i 层至多有m^(i-1)个结点(i>=1)

二叉树

定义

每个结点至多只有两棵子树(即二叉树中不存在度大于2的结点),并且二叉树的子树有左右之分,其次序不能任意颠倒。

五种基本形态

满二叉树
完全二叉树
二叉排序树
平衡二叉树

image-20230319141923208

二叉树性质

n0=n2+1

image-20230319143016702

image-20230319143028893

image-20230319143047448

image-20230319143210893

image-20230319143508321

二叉树的存储结构

顺序存储
#define MaxSize 100
struct TreeNode{
    ElemType value;//结点中的数据元素
    bool isEmpty;//节点是否为空
}
TreeNode t[MaxSize];

image-20230319144055266

image-20230319144258173

image-20230319144342500

链式存储
struct ElemType{
   int value;
};
typedef struct BiTNode{
   ElemType data;
   struct BiTNode *lchild,*rchile;//左右孩子指针
}BiTNode,*BiTree;
​
//定义一棵空树
BiTree root=NULL;
​
//插入根节点
root=(BiTree)malloc(sizeof(BiTNode));
root->data={1};
root->lchild=NULL;
root-<rchile=NULL;
​
//插入新节点
BiTNode *p=(BiTNode*)malloc(sizeof(BiTNode));
p->data={2};
p->lchild=NULL;
p->rchild=NULL;
root->lchild=p;//做为根结点的左孩子

二叉树的遍历

先序遍历
//先序遍历
void PreOrder(Tree &t){
   if (t != NULL)
  {
       // visit(T);
       cout << t->data << " ";
       PreOrder(t->lchild);
       PreOrder(t->rchild);
  }
}
中序遍历
// 中序遍历
void MidOrder(Tree &t)
{
   if (t != NULL)
  {
       MidOrder(t->lchild);
       // visit(T);
       cout << t->data << " ";
       MidOrder(t->rchild);
  }
}
后序遍历
// 后序遍历
void PostOrder(Tree &t)
{
   if (t != NULL)
  {
       PostOrder(t->lchild);
       PostOrder(t->rchild);
       // visit(T);
       cout << t->data << " ";
  }
}
层序遍历

image-20230327102842897

// 层序遍历
void ceng(Tree &t){
   queue<Node*> tq;
   Node *temp;
   tq.push(t);
   while(tq.empty()){
       temp = tq.front();
       tq.pop();
       if (temp->lchild!=NULL)
           tq.push(temp->lchild);
       if (temp->rchild != NULL)
           tq.push(temp->rchild);
  }
}
由遍历序列构造二叉树

一定都需要有中序序列

image-20230327103119134

image-20230327104556235


线索二叉树

建立

image-20230327113458974

重点:建立先序线索二叉树的时候要先判断左子树是否已经线索化再递归遍历,否则就会遍历会前驱然后反复循环

要在程序中处理最后一个节点,如果最后一个节点的右孩子为空则

image-20230329201104966

找前驱后继

image-20230329213206294

树的存储结构

image-20230329215841847

树和森林的遍历

image-20230329221821281

哈夫曼树

image-20230330142357067

并查集

image-20230330153336437

基本概念

image-20230812155333446

图的存储

邻接矩阵法

邻接表法

image-20230405114700978

image-20230405114757610

十字链表法

image-20230405112855230

即:顶点结点中绿色色块代表由某条弧指向另一个顶点

橙色色块代表被某个顶点指向

弧结点中下面的色块,绿色代表都是同一个弧尾也即是同一个顶点指向其他顶点,橙色部分代表都指向同一个顶点

重点还是看弧结点中上面的色块很明显的表示了由哪个顶点指向哪个顶点,找某个顶点的出度就是从绿色色块出发,入度就是从橙色色块出发

只能存储有向图

空间复杂度O(|V|+|E|)

邻接矩阵存储无向图,会出现时间复杂度高O(|V|^2)

邻接表存储会出现每条边都有两份冗余信息,删除顶点、边等操作时间复杂度高

邻接多重表

image-20230405113608810

总结

image-20230405114438519

图的基本操作

图的遍历

广度优先遍历

image-20230410101346942

深度优先搜索

image-20230410103236596

最小生成树

Prim算法

image-20230410104242150

image-20230410104819260

image-20230410104850421

image-20230410105124926

Kruskal算法

image-20230410104357280

image-20230410105658602

image-20230410105723631

最短路径

单源最短路径

BFS

image-20230410111404587

迪杰斯特拉算法

image-20230411144319011

Floyd

image-20230411145418963

image-20230411150443945

for(int k=0; k<n; k++){//使用Vk做为中转点
   for(int i=0;i<n;i++)//遍历矩阵
       for(int j=0;j<n;j++){
           if(A[i][j]>A[i][k]+A[k][j]){//若以Vk做为中转点路径更小
               A[i][j]=A[j][k]+A[k][j];//更新最短路径
               path[i][j]=k;//中转点
          }
      }
}
总结

image-20230411151907639

DAG有向无环图

若一个有向图中不存在环,则称为有向无环图。

拓扑

拓扑排序

image-20230411154749383

image-20230411155709824

image-20230411155854709

image-20230411155919405

时间复杂度O(|V|+|E|),若是邻接矩阵存储,时间复杂度为O(V2)

逆拓扑排序

删除出度为0结点

邻接矩阵使用比较好,或逆邻接表

image-20230411161006873

image-20230411161405733

总结

image-20230411161507427

关键路径

AOE网

image-20230411161801294

image-20230411205952400

image-20230411210118776

image-20230411212502865

有可能有多条

image-20230411213015047

求解方法

image-20230411213046244

查找

顺序查找

查找判定树

image-20230418152538988

折半查找

int Binart_search(Stable l,int ket){
   int l=0,r=l.length;
   while(l<=r){
       int mid=l+r/2;
       if(l[mid]==key)return;
       else if(l[mid]<key)l=mid+1;
       else r=mid-1;
  }
   return -1;
}

image-20230418155305920

分块查找(手算模拟)

image-20230418163244215image-20230418163325898image-20230418163347946

二叉排序树

image-20230422095747975

image-20230422101903883

平衡二叉树

(一般选择手算)

平衡二叉树(Balanced Binary Tree),简称平衡树(AVL树)―—树上任一结点的左子树和右子树的高度之差不超过1。

结点的平衡因子=左子树高-右子树高

调整最下不平衡子树

image-20230422102411233

image-20230422103139228

LL(右旋)

RR(左旋)

LR(左旋再右旋)

RL(右旋再左旋)

image-20230422105216518

image-20230422111718256

image-20230422111850337

删除操作

image-20230424162356146

image-20230424162502221

红黑树

image-20230424193055807

image-20230427155748141

image-20230427155855719

插入

image-20230427153549920

image-20230427154905905

删除(未看)

B树和B+树

B树性质

image-20230427162001205

image-20230427162448872

image-20230427162911501

B树插入与删除

插入

image-20230427164716373

删除

image-20230427165228771

image-20230427165334474

B+树

image-20230427170701297

散列表

image-20230427213639758

image-20230427213733052

排序

Data Structure Visualization (usfca.edu)

稳定性:关键字相同的元素经过排序后相对的位置是否会改变

内部排序:数据都在内存中

外部排序:数据太多,无法全部放入内存

插入排序

算法思想:每一次将一个待排序的记录按其关键字大小插入到前面已排序好的子序列中,直到全部记录插入完成。

#include<bits/stdc++.h>
using namespace std;
void insert_sort(int* unsort,int n){
   for(int i=1;i<n;i++){//从第二个元素开始比较进行插入排序
           int temp=unsort[i];
           cout<<"当前待排序的值为:"<<temp<<endl;
           int index=i;//插入的位置
           for(int j=i-1;j>=0;j--){
               if(temp<unsort[j]){//若当前元素小于排序区,则排序区后移一个元素
                   unsort[j+1]=unsort[j];
                   index=j;//插入元素位置为后移元素的原来的位置
              }  
               else{//若当前元素比剩下元素都大
                   index=j+1;//插入位置为剩下元素的后一个位置
                   break;
              }
      }
       unsort[index]=temp;
       for(int k=0;k<=index;k++)
           cout<<unsort[k]<<" ";
       cout<<endl;
  }
   cout<<endl;
   for(int i=0;i<n;i++)
   cout<<unsort[i]<<" ";
   return;
}
int main(){
   int n;
   cout<<"请输入待排序数组大小"<<endl;
   cin>>n;
   int unsort[n];
   cout<<"请输入待排序数组"<<endl;
   for(int i=0;i<n;i++)cin>>unsort[i];
   insert_sort(unsort,n);
}

空间复杂度:O(1)

时间复杂度:主要来自于对比关键字、移动元素,若有n个元素,则需要n-1躺处理

最好O(n)

最坏O(n^2)

平均O(n^2)

稳定性:稳定

优化(折半插入排序)

思路:先用折半查找找到应该插入的位置,在移动元素

希尔排序

算法思路:先追求表中元素部分有序,再逐渐逼近全局有序

相距d的元素当作一个子表,每个子表插入排序

d一般取值为元素个数n/2

#include<bits/stdc++.h>
using namespace std;
void shell_sort(int* unsort,int n){
 int d,i,j;
 for(d=n/2;d>=1;d=d/2){
     for(i=d;i<n;i++){
         int temp=unsort[i];
         int index;
         for(j=i-d;j>=0;j=j-d){
             // cout<<unsort[j]<<" ";
             if(temp<unsort[j]){
                 unsort[j+d]=unsort[j];
                 index=j;
            }
             else{
                 index=j+d;
                 break;
            }
        }
         unsort[index]=temp;
    }
}
 for(i=0;i<n;i++)
 cout<<unsort[i]<<" ";
​
 cout<<endl;
   return;
}
int main(){
   int n;
   cout<<"请输入待排序数组大小"<<endl;
   cin>>n;
   int unsort[n];
   cout<<"请输入待排序数组"<<endl;
   for(int i=0;i<n;i++)cin>>unsort[i];
   shell_sort(unsort,n);
}

空间复杂度:O(1)

时间复杂度:O(无法用数学手段证明确切的时间复杂度)

最坏O(n^2)

当n在某个范围内时,可达O(n^1.3)

稳定性:不稳定

适用性:仅适用于顺序表,因为要用d(所以要有随即范围 的特性)

image-20230503161047797

冒泡排序

属于交换排序(冒泡排序、快速排序)的一种

#include<bits/stdc++.h>
using namespace std;
void bubble_sort(int* unsort,int n){
   for(int i=0;i<n-1;i++){
       for(int j=0;j<n-i-1;j++){
           if(unsort[j]>unsort[j+1])
          {
               int temp=unsort[j];
               unsort[j]=unsort[j+1];
               unsort[j+1]=temp;
          }
      }
  }
   for(int i=0;i<n;i++)
   cout<<unsort[i]<<" ";
​
   cout<<endl;
       return;
}
int main(){
   int n;
   cout<<"请输入待排序数组大小"<<endl;
   cin>>n;
   int unsort[n];
   cout<<"请输入待排序数组"<<endl;
   for(int i=0;i<n;i++)cin>>unsort[i];
   bubble_sort(unsort,n);
}

空间复杂度:O(1)

时间复杂度:O(n^2)

稳定性:稳定的

如果某一躺排序过程中未发生”交换”则算法可提前结束

image-20230503163626878

快速排序*

1、快速排序的基本思想:

快速排序使用分治的思想,通过一趟排序将待排序列分割成两部分,其中一部分记录的关键字均比另一部分记录的关键字小。之后分别对这两部分记录继续进行排序,以达到整个序列有序的目的。

2、快速排序的三个步骤:

(1)选择基准:在待排序列中,按照某种方式挑出一个元素,作为 “基准”(pivot)

(2)分割操作:以该基准在序列中的实际位置,把序列分成两个子序列。此时,在基准左边的元素都比该基准小,在基准右边的元素都比基准大

(3)递归地对两个序列进行快速排序,直到序列为空或者只有一个元素。

3、选择基准的方式

对于分治算法,当每次划分时,算法若都能分成两个等长的子序列时,那么分治算法效率会达到最大。也就是说,基准的选择是很重要的。选择基准的方式决定了两个分割后两个子序列的长度,进而对整个算法的效率产生决定性影响。

最理想的方法是,选择的基准恰好能把待排序序列分成两个等长的子序列

我们选取固定位置(第一个元素为基准)

#include<bits/stdc++.h>
using namespace std;
int partition(int* unsort,int low,int high){
   int pivot=unsort[low];
   while(low<high){
       while(low<high&&unsort[high]>=pivot)--high;
       swap(unsort[low],unsort[high]);
       while(low<high&&unsort[low]<=pivot)++low;
       swap(unsort[low],unsort[high]);
  }
   unsort[low]=pivot;
   return low;
}
void quick_sort(int* unsort,int low,int high){
   if(low<high){
       int pivotpos=partition(unsort,low,high);//划分
       quick_sort(unsort,low,pivotpos-1);
       quick_sort(unsort,pivotpos+1,high);
  }
       return;
}
int main(){
   int n;
   cout<<"请输入待排序数组大小"<<endl;
   cin>>n;
   int unsort[n];
   cout<<"请输入待排序数组"<<endl;
   for(int i=0;i<n;i++)cin>>unsort[i];
   quick_sort(unsort,0,n);
   for(int i=0;i<n;i++)
   cout<<unsort[i]<<" ";
   cout<<endl;
}

算法效率:

时间复杂度:每一层quicksort只需要处理剩余的待排序元素,时间复杂度=O(n*递归层数) 最好:O( n*log2 n) 最坏O(n^2)

空间复杂度:O(递归层数)

最好O(log2 n)

最坏 O(n)

稳定性:不稳定

image-20230503193430694

image-20230503194103308

简单选择排序

选择排序:每一趟在待排序元素中选取关键字最小(或最大)的元素加入有序子序列—–(简单选择排序,堆排序)

#include<bits/stdc++.h>
using namespace std;
​
void select_sort(int* unsort,int n){
   for(int i=0;i<n-1;i++){
       for(int j=i+1;j<n;j++)
           if(unsort[i]>unsort[j])
           swap(unsort[i],unsort[j]);
  }
   return;
}
int main(){
   int n;
   cout<<"请输入待排序数组大小"<<endl;
   cin>>n;
   int unsort[n];
   cout<<"请输入待排序数组"<<endl;
   for(int i=0;i<n;i++)cin>>unsort[i];
   select_sort(unsort,n);
   for(int i=0;i<n;i++)
   cout<<unsort[i]<<" ";
   cout<<endl;
}

空间复杂度:O(1)

时间复杂度:O(n^2)

稳定性:不稳定

image-20230503195206854

堆排序*

image-20230503195516478

完全二叉树中

根大于左右孩子—>大根堆

根小于左右孩子—>小根堆

大根堆(代码)

image-20230503200153572

#include<bits/stdc++.h>
using namespace std;
​
//将以k为根的子树调整为大根堆
void heapadjust(int *unsort,int k,int n){
   int temp=unsort[k];
   for(int i=2*k;i<=n;i*=2){//左孩子开始
       if(i<n&&unsort[i]<unsort[i+1])//i<n-1才能保证有右孩子,并比较左右孩子
           i++;//i指向大的孩子
       if(unsort[k]>unsort[i])//是大根,退出
           break;
       else{
           swap(unsort[k],unsort[i]);
           k=i;//修改k值方便继续筛选
      }
  }
   // unsort[k]=temp;
}
//建立大根堆
void buildmaxheap(int *unsort,int n){
   for(int i=n/2;i>0;i--){
       heapadjust(unsort,i,n);
  }
}
​
//基于大根堆进行排序
void big_heap_sort(int *unsort,int n){
   buildmaxheap(unsort,n);
   for(int i=1;i<=n;i++)
   cout<<unsort[i]<<" ";
   cout<<endl;
   for(int i=n;i>1;i--)
      {
           swap(unsort[1],unsort[i]);
           heapadjust(unsort,1,i-1);
      }
   return;
}
​
/*
大根堆测试数据
53 45 87 32 17 65 78 9
调整为大根堆为
87 45 78 32 17 65 53 9
排序后为
9 17 32 45 53 65 78 87
*/
int main(){
   int n;
   cout<<"请输入待排序数组大小"<<endl;
   cin>>n;
   int unsort[n+1];
   cout<<"请输入待排序数组"<<endl;
   for(int i=1;i<=n;i++)cin>>unsort[i];
   big_heap_sort(unsort,n);
   for(int i=1;i<=n;i++)
   cout<<unsort[i]<<" ";
   cout<<endl;
}

算法效率

image-20230503204745503

image-20230503205052456

image-20230503205244334

稳定性:不稳定

image-20230503205457966

堆的插入与删除

image-20230503210215554

归并排序

#include<bits/stdc++.h>
using namespace std;
int tmp[999];
void merge_sort(int *q, int l, int r)
{
   if (l >= r) return;
//划分
   int mid = l + r >> 1;
   merge_sort(q, l, mid);
   merge_sort(q, mid + 1, r);
   //合并
   int k = 0, i = l, j = mid + 1;
   while (i <= mid && j <= r)
       if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
       else tmp[k ++ ] = q[j ++ ];
   //剩余
   while (i <= mid) tmp[k ++ ] = q[i ++ ];
   while (j <= r) tmp[k ++ ] = q[j ++ ];
   //赋值给原始数组
   for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
​
}
int main(){
   int n;
   cout<<"请输入待排序数组大小"<<endl;
   cin>>n;
   int unsort[n];
   cout<<"请输入待排序数组"<<endl;
   for(int i=0;i<n;i++)cin>>unsort[i];
   merge_sort(unsort,0,n);
   for(int i=0;i<n;i++)cout<<unsort[i]<<" ";
   cout<<endl;
}

效率

image-20230503213313872

image-20230503213328749

基数排序

image-20230503214305647

image-20230503214620519

image-20230503214924192

使用队列,先进先出,稳定的

image-20230503215743846

外部排序

image-20230504101506720

优化

多路归并

image-20230504101648768

image-20230504103507515

image-20230504103709681

败者树

image-20230504114522930

image-20230504114818321

置换选择排序

选择最小置换出去,直到内存满了则进行下一个初始归并段

image-20230504172026854

最佳归并树

image-20231023160619054

image-20231023161520937

定义代码

定义顺序存储的二叉树(从数组下标1开始存储)

二叉树顺序存储的数据结构定义,需要注意以下两点:

\1. 二叉树的结点用数组存储,每个结点需要标记“是否为空”

\2. 各结点的数组下标隐含结点关系,要能根据一个结点的数组下标 i,计算出其父节点、左孩子、右孩子的数组下标

typedef struct TreeNode {
    int data;       //结点中的数据元素
    bool isEmpty;   //结点是否为空
} TreeNode;

//初始化顺序存储的二叉树,所有结点标记为"空"
void InitSqBiTree (TreeNode t[], int length) {
    for (int i=0; i<length; i++){
        t[i].isEmpty=true;
    }
}

int main(){
    TreeNode t[100];        //定义一棵顺序存储的二叉树
    InitSqBiTree(t, 100);   //初始化为空树
    //...
}

双向链表建立链栈


//定义栈结点
typedef struct DbSNode{			    //定义双链表结点类型
    int data;				        //每个节点存放一个数据元素
    struct DbSNode *last,*next;	    //指向前后两个结点
}DbSNode;

typedef struct DbLiStack{	        //双链表实现的栈(栈顶在链尾)
    struct DbSNode *head, *rear;    //两个指针,分别指向链头、链尾
}DbLiStack, *DbStack;

//初始化一个链栈(单链表实现,栈顶在链头)
bool InitDbStack(DbStack &S) {
    S = (DbLiStack *) malloc(sizeof(DbLiStack));    //初始化一个链栈(双链表实现,栈顶在链尾)
    DbSNode * p = (DbSNode *) malloc(sizeof(DbSNode)); //新建一个头结点
    p->next = NULL;         //头结点之后暂时还没有节点
    p->last = NULL;         //头结点之前没有节点
    S->head = p;
    S->rear = p;
    return true;
}

使用“双亲表示法”定义顺序存储的树(以及森林)

typdef struct PNode{
	int date;//数据元素
    int parent;//双亲
}PNode;
typedef struct PTree{
    PNode pnode[maxsize];
    int num;
}

写代码:使用“孩子表示法”,定义链式存储的树(以及森林)

//Child表示下一个孩子的信息
typedef struct Child{
    int index;             //孩子编号
    struct Child * next;   //下一个孩子
} Child;

//TreeNode用于保存结点信息
typedef struct TreeNode {
    char data;             //结点信息
    Child * firstChild;    //指向第一个孩子
} TreeNode;

TreeNode tree[10];   //定义一棵拥有10个结点的树(孩子表示法

图的邻接表存储

typedef struct ArcNode{			//边表结点
	int adjvex;					//该弧所指向的顶点的位置
	struct ArcNode *next;		//指向下一条弧的指针
	//InfoType info;			//网的边权值
}ArcNode; 

typedef struct VNode{			//顶点表结点
	char data; 			        //顶点信息
	ArcNode *first; 			//指向第一条依附该顶点的弧的指针
}VNode;

VNode graph[10];               //定义一个拥有10个顶点的图(邻接表法)

使用孩子兄弟法表示

typedef struct CSNode{ 
     ElemType data; //数据域 
     struct CSNode *firstchild,*nextsibling; //第一个孩子和右兄弟指针 
}CSNode,*CSTree;

定义并查集

#define SIZE 13
int UFSets[SIZE];		//用一个数组表示并查集

//初始化并查集
void Initial(int S[]){
    for(int i=0;i<SIZE;i++) S[i]=-1; } //Find “查”操作,找x所属集合(返回x所属根结点) int Find(int S[],int x){ while(S[x]>=0)			//循环寻找x的根
        x=S[x];
    return x;						//根的S[]小于0
}

//Union “并”操作,将两个集合合并为一个
void Union(int S[],int Root1,int Root2){
  	//要求Root1与Root2是不同的集合
  	if(Root1==Root2)	return;		
  	//将根Root2连接到另一根Root1下面
    S[Root2]=Root1;
}

//压缩find
int find(int s[],int x){
    int root=x;//root为根节点
    while(root>=0){
		root=s[root];
    }
    while(root!=x){//根节点不是当前节点,那就压缩
        int t=s[x];//辅助x的父节点
        s[x]=root;//把当前节点挂到根节点上
        x=s[x];//接着压缩x父节点
    }
    return 1;
}

快速排序

int partition(int *s,int low,int high){
   int pivot=s[low];
   while(low<high){
       while(low<high&&s[high]<pivot)high--;
       swap(s[low],s[high]);
       while(low<high&&s[low]>pivot)low++;
       swap(s[low],s[high]);
  }
   s[low]=pivot;
   return low;
}
void quick_sort(int *s.int low,int high){
   if(low<high){
       int pivotpos=partition(s,low,high);
       quick_sort(s,low,pivotpos-1);
       quick_sort(s,pivotpos+1,high);
  }
   return;
}
赞赏

微信赞赏 支付宝赞赏

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注