数据结构之排序

目录

 

冒泡排序

选择排序

插入排序

shell排序

归并排序

快速排序

堆排序


冒泡排序

void BubbleSort(int arr[],int _size)
{
       int i = 0;
       for (; i < _size-1; ++i)
       {
              int j = 0;
for (; j < _size-1-i; ++j)
              {
                     if (arr[j]>arr[j + 1])
                     {
                           Swap(&arr[j], &arr[j + 1]);
                     }
              }
       }
}

选择排序

/*
每一轮循环都把最小的数放在数组的前半部分
*/
void SelectSort(int arr[], int _size)
{
       int i = 0;
       int j = 0;
       int min = 0;
       for (i = 0; i < _size - 1; i++)//i之前为已排序数组
       {
              min = i;//min为已排序的后一位下标
              for (j = i + 1; j < _size; j++)
              {
                     if (arr[j] < arr[min])
                     {
                           min = j;//更新最小值的下标
                     }
              }
              if (arr[min] != arr[i])//如果min已被更新
              {
                     Swap(&arr[min], &arr[i]);
              }
       }
}

插入排序

/*
插入排序
1.从第二个元素开始,标记该元素
2.逐个与前面的数比较
3.最后再把标记的元素放入合适位置
时间复杂度O(N^2)
*/

void InsertionSort(int arr[], int _size)
{
       for (int i = 1; i < _size; i++)//从第二个开始
       {
              int key = arr[i];//标记即将插入的数字
              int j = i - 1;//从key的前一位开始比较
while (j >= 0 && arr[j]>key)//在已排序队列中倒着找到比自己小那位
              {
                     arr[j + 1] = arr[j];//比key大的往后挪
                     j--;
              }
              arr[j + 1] = key;
       }
}

shell排序

1.先定好步长step * 3 + 1
2.以当前步长逐个向后比较
3.缩步长
 

void ShellSort(int arr[], int _size)
{
       int i = 0;
       int j = 0;
       int key = 0;
       int step = 0;
       while (step < _size)
       {
              step = step * 3 + 1;//定步长
       }
       while (step>0)
       {
              for (i = step; i < _size; ++i)
              {
                     key = arr[i];//先标记要交换的位置
                     j = i - step;//步长向前一位
                     while (j>=0&&arr[j]>key)//如果步长前面的数大于key
                     {
                           arr[j + step] = arr[j];//往后挪
                           j -= step;//步长往前踏
                     }
                     //当把步长内大于key的全部元素放到后面,再安置key
arr[j + step] = key;
              }
              step = (step - 1) / 3;//一轮挪完后
       }
}


归并排序

1.定义一个第三方
2.一边从起始位置开始,一边从中间开始,比较小的先加入第三方
3.如果数组个数为奇数,看最后哪一方还剩下一个
4.把剩下的加进去
 

void Merge(int arr[], int start, int end, int mid)
{
       int len = end - start + 1;
       int* tmp = (int*)malloc(sizeof(int)*len);
       int index = 0;
       int i= start;
       int j = mid + 1;
       while (i<=mid&&j<=end)//任何一边到了末尾结束
       {
              tmp[index++] = (arr[i] <= arr[j] ? arr[i++]:arr[j++]);
       }
       while (i <= mid)//如果j先结束
       {
              tmp[index++] = arr[i++];
       }
       while (j <= end)//如果i先结束
       {
              tmp[index++] = arr[j++];
       }
       for (i = 0; i < len; i++)
       {
              arr[start++] = tmp[i];
       }
}
//递归
void MergeSortRecur(int arr[], int start,int end)
{
       if (start==end){
              return;
       }
       int mid = (start + end) >> 1;
       MergeSortRecur(arr, start, mid);
       MergeSortRecur(arr, mid+1, end);
       Merge(arr, start, end, mid);
}
//非递归
void MergeSortIter(int arr[], int size)
{
       int left, mid, right;
       //int i;
       for (int i = 1; i < size; i *= 2)
       {
              left = 0;
              while (left+i < size)
              {
                     mid = left + i - 1;
                     right = mid + i < size ? mid + i : size - 1;
                     Merge(arr, left, right, mid);
                     left = right + 1;
              }
       }
}

快速排序

void QuickSort(int arr[], int start, int right)//先全体找出index
{
       if (start>right)
       {
              return;
       }
       int index = arr[start];//将最左边的数作为基准值,这点要求了必须从右边开始
       int i = start;
       int j = right;
       while (i != j)       {
              while (arr[j] >= index&&i < j)//从右往左找,知道找到比index小的为止
              {
                     j--;
              }
              while (arr[i] <= index&&i < j)
              {
                     i++;
              }
              if (i<j)//要是大于则不交换
                     Swap(&arr[i], &arr[j]);
       }
       arr[start] = arr[i];//走到这里因为是j先走,所以j可能先跳出循环,而i还停留在上一个小于index的位置上,即保
证arr[i]肯定是小于index的,所以才能交换
       arr[i] = index;
       QuickSort(arr, start, i - 1);//再找左半区的
       QuickSort(arr, i + 1, right);//右半区
}

堆排序
 

void AdjustUp(int arr[],int index, int size)
{
       int left = index * 2 + 1;
       int right = index * 2 + 2;
       int max = index;
       if (left < size&&arr[left]>arr[max])//找较大的子节点
       {
              max = left;
       }
       if (right < size&&arr[right]>arr[max])//找较大的子节点
       {
              max = right;
       }
       if (max != index)
       {
              Swap(&arr[max], &arr[index]);
              AdjustUp(arr, max, size);
       }
}
void AdjustDown(int arr[], int index, int size)
{
       int child = index * 2 + 1;//子节点
       while (child<size)
       {
              if (child + 1<size && arr[child] > arr[child + 1])//子节点中找较小的
              {
                     child++;
              }
              if (arr[index] < arr[child])//因为是从底层往上把那个较小值上调的,所以这时候的index往下之
前已经调整过了
              {
                     break;//一旦发现父节点比子节点小的话,直接结束这次的调整
              }
              Swap(&arr[index], &arr[child]);//走到这里说明没有进入上一个if,此时的根节点比子节点大
              index = child;//子节点做根节点继续往下调整
              child = index * 2 + 1;
       }
}
void MakeHeap(int arr[], int size)//建堆
{
       int i = 0;
       for (i = size / 2 - 1; i >= 0; i--)//把所有的非叶子节点都要调整
       {
              AdjustDown(arr, i, size);
              //AdjustUp(arr, i, size);
       }
}
void HeapSort(int arr[], int size)
{
       int end = 0;
       MakeHeap(arr, size);//小堆创建完,此时的根节点为整个数组中最小的节点
       for (end = size - 1; end >= 0; end--)//每次把根节点和最末尾的end节点交换,end--
       {
              Swap(&arr[end], &arr[0]);
              AdjustDown(arr, 0, end);//现在从根节点开始调整,不同于上面的倒数第一个非叶子节点
              //AdjustUp(arr, 0, i);
       }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值