一 排序算法
1.插入排序
思想:假如有n个元素,我们从第二个元素开始,依次与前面的元素比较,如果小于,前面的元素往后挪,但注意的是往后挪的过程中会覆盖后面的元素,所以我们要定义一个变量保存后面的元素。
然后再把保存的变量赋给空出来的位置,外层循环注意是从第二个元素开始,内层循环注意的是外层循环的上一个元素开始比较。
附加数组宏函数打印
#define LOG_CARRY 1
#ifdef LOG_CARRY//打印数组
#define log_carry(BUFSIZ,len) \
do \
{ \
for(int i = 0;i<len;i++) \
{ \
printf("%4d ",BUFSIZ[i]); \
} \
}while(0); \
printf("\n")
#endif
int insert_sort( int* source,int length){
if(!*source) return -1;
for(int i = 1 ; i < length ;i++){
int temp =source[i];
int j=i-1;
while (j >= 0 && temp < source[j])
{
source[j+1] = source[j];
j--;
}
source[j+1] = temp;
}
return 1;
}
1.希尔排序
思想:希尔排序是对直接插入排序的改进,建立在直接排序的基础上实现的。希尔排序只是增加了一个增量,增量是递减的我们可以每次都除以2来作为增量,注意最后的增量必须是1。说白了就是插入排序的一种改进为什们这么说呢,插入排序其实就是每一次都移动一个位置进行比较,而希排序就是把一个位置变成一个增量来比较排序的。
int shell_sort(int* source,int length){
if(!*source) return -1;
for(int key=length / 2;key > 0; key /= 2)
{
for(int i=key; i < length; i += key)
{
int temp = source[i];
int j=i-key;
while(j >= 0 && temp < source[j])
{
source[j+key] = source[j];
j -=key;
}
source[j+key] = temp;
}
}
return 1;
}
}
3.快速排序 思想:快速排序分两步
a.找中轴(属于它的位置)
b.递归
首先我们要找中轴,找中轴比如说第一次把第一个元素作为要要找的元素,通过前后交换对比找到它应有的位置,就是让他左边的元素都小于它,右边的元素都大于他。这样第一趟完后数组基本上有序。
同样的方法,然后我们以中轴为中心对它左边的元素递归排序,同样对它右边的右的元素进行递归排序
int Find_axis(int* source, int left ,int right){
int temp=source[left];
while (left < right)
{
while(left < right && temp <= source[right]) right--;
if(left <right)
{
source[left] = source[right];
}
while(left <right && temp >= source[left]) left++;
if(left < right)
{
source[right] = source[left];
}
}
source[left] = temp;
return left;
}
int Quick_Sort(int* source, int left,int right){
if(!*source) return -1;
if(left <right){
int axis=Find_axis(source, left, right);//找中轴
Quick_Sort(source,left,axis-1);//左边递归
Quick_Sort(source,axis+1,right);//右边递归
}
}
int main(){
int Array[]={21,34,33,11,1,123,3,23,90,2};
int length = sizeof(Array)/sizeof(Array[0]);
log_carry(Array,length);
#if 0
insert_sort(Array,length);
shell_sort(Array,length);
#else
Quick_Sort(Array,0,length-1);
#endif
log_carry(Array,length);
return 0;
}
4.折半插入排序 思想:其实折半插入排序算法就是插入算法的改进。插入算法是,从第二个元素开始后面的每一个元素往前面插入,然而我们在插入的时候从开始插入的上一个元素开始每一个元素都要比较直到找到要插入的位置。但是前面的元素都是有顺序的,我们每一个元素都要比较。这样就降低了效率。他前面所有的元素都有序。那我们可不可以找一个元素先跟要插入的元素进行比较。如果小就在他的前面找插入的位置。反之如果大于就在他的后面找要插入对的位置。这就是折半折半插入排序的思想。所以只是改变了一下前面要插入的方式。是先找,在比较,在插入。而不是每一个都要比较。则那样去找那个要比较的元素。
我们定义一个left变量让他指向第一个元素,及left =0 .定义一个right指向要插入的前面的位置及,right=i-1;
我们在定义一个变量middle 每次它指向left 和right的中间的元素,所以这样就好办了。比较。如果小就在他的前面找插入的位置middle=right-1。反之如果大于就在他的后面找要插入对的位置middle=left+1;然后在移动进行插入后面的跟插入排序一样。
int In_Half_Sort(int *source,int length)
{
if(!*source) return -1;
int tmp, left, right,middle;
for (int i = 1; i < length; i++)
{
tmp = source[i];
left = 0;
right = i - 1;
while (left <= right)
{
middle = (left + right) / 2;
if (source[middle] > tmp)
{
right = middle - 1;
}
else
{
left = middle + 1;
}
}
for (int j = i-1; j >= right + 1; j--)
{
source[j + 1] = source[j];
}
source[right + 1] = tmp;
}
return 1;
}
6.二路 归并排序
思想:
二路归并排序是采用分而至之的思想,先把序列分成两部分,然后在采用递归的方法对它排序。递归就是对两边的序列依次分成两个序列然后在递归,这样依次下去,然后在对排序好的数组并归,最后对两个子序列合并就好了。这样就对这个数组排序好了。
int Merge(int * Array, int low, int mid, int high)
{
int i = low, j = mid + 1, p = 0;//对应Array数组的下标
int * r = new int[high - low + 1];//申请另一个对应大小的数组来存放排好序的数据
while (i <= mid && j <= high)
{
r[p++] = (Array[i] <= Array[j]) ? Array[i++] : Array[j++];
}
//最后左边子序列剩余的元素依次拷入到临时的数组中
while (i <= mid)
r[p++] = Array[i++];
//最后右边子序列剩余的元素依次拷入到临时的数组中
while (j <= high)
r[p++] = Array[j++];
for (p = 0, i = low; i <= high; p++, i++)
Array[i] = r[p];//最后再把有序数据存入到原先的数组中,使得Array数组对应部分数据有序
delete[] r;
return 1;
}
//自顶向下(递归实现)
int MSort(int *Array, int low, int high)
{
if (low<high)
{
int mid = (low + high) / 2;//取中间值
MSort(Array, low, mid);//左边递归
MSort(Array, mid + 1, high);//右边递归
Merge(Array, low, mid, high);//最后合并两个序列
}
return 1;
}
7.冒泡排序 思想:每一趟两个相邻的元素进行比较,找出一个最大的放在后面,外层循环要注意的是,如果是n个元素,要n-1趟,内层循环注意的是n-1-i,因为每一趟找出一个最大的放在后面,后面的不用比较
int Bubbing(int *source,int length){
for(int i=0;i<length-1;i++) {
int key = -1;
for(int j = 0; j < length - 1 - i; j++){
if(source[j]>source[j+1])
{
int tmp=source[j];
source[j]=source[j+1];
source[j+1]=tmp;
key = 1;
}
}
if(key == -1) return 1;
}
return 1;
}
8.选择排序 思想:如果有n个元素,我们要固定n-1次,因为最后面一个元素不用比较。每一次固定一个元素后面的所有元素都要进行比较,如果小于就交换。外层循环注意的是固定n-1次,内层循环注意得是从固定元素的下一个元素开始比较
int Select(int* source ,int length){
for(int i=0; i < length - 1; i++)
{
for(int j=i+1;j < length;j++)
{
if(source[i]>source[j])
{
int tmp=source[i];
source[i]=source[j];
source[j]=tmp;
}
}
}
return 1;
}
二,KMP 字符串处理
kmp 算法第一 先求出next的数组,next是求出最大公共元素单元的素组
// pattern
//
// abcabcd
// k = 0
// q = 1
void make_next(const char *pattern, int *next) {
int q, k; //q
int m = strlen(pattern);
next[0] = 0; //
for (q = 1,k = 0;q < m; q ++) {
while (k > 0 && pattern[q] != pattern[k]) {
k = next[k-1];
}
if (pattern[q] == pattern[k]) { // 如果前缀与后缀有相同的字符
k ++;
}
next[q] = k;
}
}
int kmp(const char *text, const char *pattern, int *next) {
int n = strlen(text);
int m = strlen(pattern);
make_next(pattern, next);
int i, q;
for (i = 0, q = 0;i < n;i ++) { //i --> text, q --> pattern
#if 1
while (q > 0 && pattern[q] != text[i]) {
q = next[q-1];
}
#endif
if (pattern[q] == text[i]) {
q ++;
}
// q == m --->
if (q == m) {
return i-q+1;
}
}
return -1;
}
二. 代码部分
//Sort.c 文件
//Sort.c 文件
#include <stdio.h>
#include <stdlib.h>
#include "malloc.h"
#include "Prinf.h"
/*
for(int i=1;i<n;i++)
{
int tmp=a[i];
int j=i-1;
while(j>0&&tmp>a[j])
{ a[j+1]=a[j];
j--;
}
a[j+1]=tmp;
}
*/
int insert_sort( int* source,int length){
if(!*source) return -1;
for(int i = 1 ; i < length ;i++){
int temp =source[i];
int j=i-1;
while (j >= 0 && temp < source[j])
{
source[j+1] = source[j];
j--;
}
source[j+1] = temp;
}
return 1;
}
int shell_sort(int* source,int length){
if(!*source) return -1;
for(int key=length / 2;key > 0; key /= 2)
{
for(int i=key; i < length; i += key)
{
int temp = source[i];
int j=i-key;
while(j >= 0 && temp < source[j])
{
source[j+key] = source[j];
j -=key;
}
source[j+key] = temp;
}
}
return 1;
}
#if 0
int find_axis(int *arr,int left,int right)
{
int tmp = arr[left];
while (left < right){
while (arr[right] >= tmp&&left < right) right --;
if (left<right)
{
arr[left] = arr[right];
}
while (arr[left]<=tmp&&left<right) left++;
if (left<right)
{
arr[right] = arr[left];
}
}
arr[left] = tmp;
return left;
}
void quick_sort(int *arr, int left, int right)
{
if (left<right)
{
int axis = find_axis(arr, left, right);//找中轴
quick_sort(arr,left, axis-1);//左边递归
quick_sort(arr, axis + 1, right);//右边递归
}
}
#endif
int Find_axis(int* source, int left ,int right){
int temp=source[left];
while (left < right)
{
while(left < right && temp <= source[right]) right--;
if(left <right)
{
source[left] = source[right];
}
while(left <right && temp >= source[left]) left++;
if(left < right)
{
source[right] = source[left];
}
}
source[left] = temp;
return left;
}
int Quick_Sort(int* source, int left,int right){
if(!*source) return -1;
if(left <right){
int axis=Find_axis(source, left, right);//找中轴
Quick_Sort(source,left,axis-1);//左边递归
Quick_Sort(source,axis+1,right);//右边递归
}
}
int In_Half_Sort(int *source,int length)
{
if(!*source) return -1;
int tmp, left, right,middle;
for (int i = 1; i < length; i++)
{
tmp = source[i];
left = 0;
right = i - 1;
while (left <= right)
{
middle = (left + right) / 2;
if (source[middle] > tmp)
{
right = middle - 1;
}
else
{
left = middle + 1;
}
}
for (int j = i-1; j >= right + 1; j--)
{
source[j + 1] = source[j];
}
source[right + 1] = tmp;
}
return 1;
}
int Bubbing(int *source,int length){
for(int i=0;i<length-1;i++) {
int key = -1;
for(int j = 0; j < length - 1 - i; j++){
if(source[j]>source[j+1])
{
int tmp=source[j];
source[j]=source[j+1];
source[j+1]=tmp;
key = 1;
}
}
if(key == -1) return 1;
}
return 1;
}
int Select(int* source ,int length){
for(int i=0; i < length - 1; i++)
{
for(int j=i+1;j < length;j++)
{
if(source[i]>source[j])
{
int tmp=source[i];
source[i]=source[j];
source[j]=tmp;
}
}
}
return 1;
}
int main(){
int Array[]={21,34,33,11,1,123,3,23,90,2};
int length = sizeof(Array)/sizeof(Array[0]);
log_carry(Array,length);
#if 0
insert_sort(Array,length);
shell_sort(Array,length);
Quick_Sort(Array,0,length-1);
In_Half_Sort(Array,length);
#else
Bubbing(Array,length);
#endif
log_carry(Array,length);
return 0;
}
// Print.h 文件
// Print.h 文件
#ifndef _PRINF_H_
#define _PRINF_H_
#define LOG_CARRY 1
#ifdef LOG_CARRY//打印数组 空位补0
#define log_carry(BUFSIZ,len) \
do \
{ \
for(int i = 0;i<len;i++) \
{ \
printf("%4d ",BUFSIZ[i]); \
} \
}while(0); \
printf("\n")
#endif
#endif //_PRINF_H_
// Merge.cpp 文件
// Merge.cpp 文件
#include<iostream>
#include<stdlib.h>
using namespace std;
#include "Prinf.h"
int Merge(int * Array, int low, int mid, int high)
{
int i = low, j = mid + 1, p = 0;//对应Array数组的下标
int * r = new int[high - low + 1];//申请另一个对应大小的数组来存放排好序的数据
while (i <= mid && j <= high)
{
r[p++] = (Array[i] <= Array[j]) ? Array[i++] : Array[j++];
}
//最后左边子序列剩余的元素依次拷入到临时的数组中
while (i <= mid)
r[p++] = Array[i++];
//最后右边子序列剩余的元素依次拷入到临时的数组中
while (j <= high)
r[p++] = Array[j++];
for (p = 0, i = low; i <= high; p++, i++)
Array[i] = r[p];//最后再把有序数据存入到原先的数组中,使得Array数组对应部分数据有序
delete[] r;
return 1;
}
//自顶向下(递归实现)
int MSort(int *Array, int low, int high)
{
if (low<high)
{
int mid = (low + high) / 2;//取中间值
MSort(Array, low, mid);//左边递归
MSort(Array, mid + 1, high);//右边递归
Merge(Array, low, mid, high);//最后合并两个序列
}
return 1;
}
int main(void)
{
int Array[] = { 12,32,11,4,6,34,43,88,78,1 };
int length=sizeof(Array)/sizeof(Array[0]);
log_carry(Array,length);
MSort(Array,0,length-1);
log_carry(Array,length);
return 0;
}