一个程序主要应该包括两方面内容:一个是对数据组织的描述,另一个则是对程序操作的描述。对数据组织的描述称为数据结构,而对程序操作的描述称为算法。因此有这样一个公式:数据结构+算法=程序。对于面向对象程序设计,强调的是数据结构,而对于面向过程程序设计,如C. Pascal. FORTRAN等语言,主要关注的是算法。
算法:解决一个问题的完整步骤描述。
五个特征:有穷、正确、可行、输入、输出。
三种基本结构:顺序、选择、循环
流程图:普通流程图 ; N-S流程图
下面介绍排序算法:
为什么介绍排序算法呢?因为 排序是数据处理中的一种重要运算。在当今计算机系统中,花费在数据排序的时间占用了一部分系统运行的时间,所以研究并采用好的排序算法,能够提高工作效率是很重要的。
//选择排序
#include<stdio.h>
int main()
{
int a[10];
int i,j,k,m;
printf("10 numbers:\n");
for(i=0;i<10;i++)
{
scanf("%d",&a[i]);
}
for(i=0;i<9;i++)
{
k=i;
for(j=i+1;j<10;j++)
if(a[k]>a[j])
k=j;
if(k!=i)
{
m=a[i];
a[i]=a[k];
a[k]=m;
}
}
printf("The sorted array is : by the chosen method .\n ");
for(i=0;i<10;i++)
{
printf("%d ",a[i]);
}
printf("\n");
}
//9 4 3 34 32 4 38 98 0 99
//堆排序
#include<stdio.h>
#define LENGTH 20
递归方式构建大根堆(len是arr的长度,index是第一个非叶子节点的下标)
void adjust(int arr[],int len,int index)
{
int left = 2*index + 1; // index的左子节点下表
int right = 2*index + 2;// index的右子节点下标
int temp;
int maxIdx=index;
if(left<len&&arr[left]>arr[maxIdx]) maxIdx=left;
if(right<len&&arr[right]>arr[maxIdx]) maxIdx=right;
if(maxIdx!=index)
{
temp=arr[maxIdx];
arr[maxIdx]=arr[index];
arr[index]=temp;
adjust(arr,len,maxIdx);
}
}
//堆排序
void heapSort(int arr[],int size)
{
int i,temp;
//构建大根堆(从最后一个非叶子节点向上)
for(i=size/2-1;i>=0;i--)
{
adjust(arr,size,i);
}
printf("the max heap:\n");
for(i=0;i<size;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
//调整大根堆
for(i=size-1;i>=1;i--)
{
temp=arr[i];
arr[i]=arr[0]; // 将当前最大的放置到数组末尾
arr[0]=temp;
adjust(arr,i,0);// 将未完成排序的部分继续进行堆排序
}
}
main()
{
int b[LENGTH];
int i;
for(i=0;i<LENGTH;i++)
{
scanf("%d ",&b[i]);
}
printf("\n");
heapSort(b,LENGTH);
for(i=0;i<LENGTH;i++)
{
printf("%d ",b[i]);
}
return 0;
}
8 9 0 2 3 4 223 4 3 78 6767 9889 78 67 56 45 34 23 21 213 99
//冒泡排序
#include<stdio.h>
main()
{
int a[10];
int i,j,k;
printf("10 numbers:\n");
for(i=0;i<10;i++)
{
scanf("%d",&a[i]);
}
for(i=0;i<9;i++)//十个数进行九趟排序
{
for(j=0;j<9-i;j++)
{
if(a[j]>a[j+1])
{
k=a[j];
a[j]=a[j+1];
a[j+1]=k;
}
}
}
printf("The sorted array is : by bubble.");
for(i=0;i<10;i++)
{
printf("%d ",a[i]);
}
printf("\n");
}
//quicksort
//对冒泡的改进
#include<stdio.h>
#define N 10000
#include<time.h>
main()
{
clock_t begin,end;
double cost;
int p(int a[],int low,int high);
void q(int a[],int low,int high);
int a[N];
int i;
//printf("please input 10 numbers.\n");
int j=1000;
begin=clock();
for(i=0;i<N;i++)
{
// scanf("%d",&a[i]);
a[i]=j--;
}
q(a,0,N-1);
end=clock();
cost=(double)(end-begin);
printf("The sorted array is : by quicksort method .\n ");
for(i=0;i<N;i++)
{
printf("%d ",a[i]);
}
printf("The cost is: %lf\n",cost);
}
int p(int a[],int low,int high)
{
int key=a[low],p;
while(low<high)
{
while(low<high&&a[high]>=key)
{
--high;
}
p=a[low];
a[low]=a[high];
a[high]=p;
while(low<high&&a[low]<=key)
{
++low;
}
p=a[high];
a[high]=a[low];
a[low]=p;
}
a[low]=key;
return low;
}
void q(int a[],int low,int high)
{
int j;
if(low<high)
{
j=p(a,low,high);
q(a,low,j-1);
q(a,j+1,high);
}
}
//quicksort
//对冒泡的改进
#include<stdio.h>
#define N 5000
#include<time.h>
main()
{
clock_t begin,end;
double cost;
int p(int a[],int low,int high);
void q(int a[],int low,int high);
int a[N];
int i;
//printf("please input 10 numbers.\n");
int j=1000;
begin=clock();
for(i=0;i<N;i++)
{
// scanf("%d",&a[i]);
a[i]=j--;
}
q(a,0,N-1);
end=clock();
cost=(double)(end-begin);
printf("The sorted array is : by quicksort method .\n ");
for(i=0;i<N;i++)
{
printf("%d ",a[i]);
}
printf("\nThe cost is: %lf\n",cost);
}
int p(int a[],int low,int high)
{
int key=a[low],p;
while(low<high)
{
while(low<high&&a[high]>=key)
{
--high;
}
p=a[low];
a[low]=a[high];
a[high]=p;
while(low<high&&a[low]<=key)
{
++low;
}
p=a[high];
a[high]=a[low];
a[low]=p;
}
a[low]=key;
return low;
}
void q(int a[],int low,int high)
{
int j;
if(low<high)
{
j=p(a,low,high);
q(a,low,j-1);
q(a,j+1,high);
}
}
OPENMP并行快排主要利用了OpenMP里面的#omp parallel sections将对两个子数组的快速排序函数用两个线程并行化执行,至于线程的创建和销毁我们不用管,只要告诉编译器哪里的代码需要并行执行就可以了,具体请看OpenMP资料。
//quicksort
//对冒泡的改进
#include<stdio.h>
#include<time.h>
#include "omp.h"
#define N 5000
#pragma warning(disable:4996)
int main()
{
omp_set_num_threads(2);//----------------设置线程数为2,因为是双核的CPU
double cost;
clock_t begin, end;
int p(int a[], int low, int high);
void q(int a[], int low, int high);
int a[N];
int b[N / 2];
int c[N / 2];
int d[N];
int j = 1000;
int i = 0,k = 0,m=0,n=0;
#pragma omp parallel default(none) shared(a,d,N) private(i)//private(list)表示每个线程的变量都是局部的,shared()表示的变量被线程组中所有线程共享,default()定义缺省范围
{ //---这个for循环是并行的
#pragma omp for
for (i = 0; i < N; i++)
{
a[i] = j;
d[i] = j;
j--;
}
}
begin = clock();
#pragma omp parallel default(none) shared(a,b,c,N/2) private(i)//---这个for循环是并行的
{
#pragma omp for
for (i = 0; i < N / 2; i++)
{
b[i] = a[i];
c[i] = a[i + N / 2];
}
}
#pragma omp parallel default(none) shared(b,c,N/2)//private(i)------快速排序的并行region
{
#pragma omp parallel sections
{
#pragma omp section
q(b, 0, N/2 - 1);
#pragma omp section
q(c, 0, N / 2 - 1);
}
}
for (; k < N; k++)//----------将D[]和E[]进行归并排序放入B[]里面
{
if (m < N / 2 && n < N / 2)
{
if (b[n] <= c[m])
{
d[k] = b[n];
n++;
}
else
{
d[k] = c[m];
m++;
}
}
if (m == N / 2 || n == N / 2)
{
if (m == N / 2)
d[k] = c[m];
else
d[k] = b[n-1];
k += 1;
break;
}
}
if (n < N / 2)
{
int tem = N / 2 - n;
int pp = 0;
for (pp = 0; pp < tem; pp++)
{
d[k] = b[n];
n++;
k++;
}
}
else if (m < N / 2)
{
int tem = N / 2 - m;
int pp = 0;
for (pp = 0; pp < tem; pp++)
{
d[k] = c[m];
m++;
k++;
}
}
end = clock();
printf("The sorted array is : by quicksort method .\n ");
for (i = 0; i < N; i++)
{
printf("%d ", d[i]);
}
cost = (double)(end - begin);
printf("\n并行时间为:%lf\n",cost);
}
int p(int a[], int low, int high)
{
int key = a[low], p;
while (low < high)
{
while (low < high && a[high] >= key)
{
--high;
}
p = a[low];
a[low] = a[high];
a[high] = p;
while (low < high && a[low] <= key)
{
++low;
}
p = a[high];
a[high] = a[low];
a[low] = p;
}
a[low] = key;
return low;
}
void q(int a[], int low, int high)
{
int j;
if (low < high)
{
j = p(a, low, high);
q(a, low, j - 1);
q(a, j + 1, high);
}
}
#include <iostream>
using namespace std;
#define LENGTH 20
//直接插入排序:将第一个数据看做一个顺序表,将后面的数据一次插入表中
void InsertSort(int a[], int n)
{
for(int i= 1; i<n; i++){
int j= i-1; //表中最后一个数据
int x = a[i]; //复制为哨兵,即存储待排序元素
while(j>=0 && x < a[j]){ //查找在有序表的插入位置 (遍历表)
a[j+1] = a[j];
j--; //元素后移
}
a[j+1] = x; //插入到正确位置
}
}
int main()
{
int b[LENGTH];
for(int i=0;i<LENGTH;i++){
printf("%d ",b[i]);
}
cout<<"\n";
InsertSort(b,LENGTH);
for(int i=0;i<LENGTH;i++)
cout<<b[i]<<" ";
return 0;
}
基本思想是:希尔排序是在插入排序的基础上进行发展的,通过一个希尔增量先排序一定间隔的数据。待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。
平均时间复杂度:O(N^3/2)
空间复杂度:O(1)
稳定性:不稳定
#include <iostream>
using namespace std;
#define LENGTH 20
void shellsort(int a[],int n) {
for (int increment = n / 2; increment > 0; increment /= 2)
{
for (int i = increment; i < n; i++)
{
int insert_num = a[i], j;
for (j = i - increment; j >= 0; j -= increment)
{
if (a[j] > insert_num)
a[j + increment] = a[j];
else
break;
}
a[j + increment] = insert_num;
}
}
}
int main()
{
int b[LENGTH];
for(int i=0;i<LENGTH;i++){
printf("%d ",b[i]);
}
cout<<"\n";
shellsort(b,LENGTH);
for(int i=0;i<LENGTH;i++)
cout<<b[i]<<" ";
return 0;
}