栈的实现:顺序存储栈:
1 #include<stdio.h>
2 #include<stdlib.h>
3 #define STACK_INIT_SIZE 100
4 #define STACKINCREMENT 10
5 typedef struct{
6 int *base;
7 int *top;
8 int stacksize;
9 }SqStack;
10 int InitStack(SqStack *s)
11 {
12 s->base=(int *)malloc(STACK_INIT_SIZE*sizeof(int));
13 if(!s->base)
14 exit(1);
15 s->top=s->base;
16 s->stacksize=STACK_INIT_SIZE;
17 return 0;
18 }
19 int GetTop(SqStack s)
20 {
21 if(s.top==s.base) return 1;
22 return *(s.top-1);
23 }
24 int Push(SqStack *s,int e)
25 {
26 if((s->top-s->base)>=s->stacksize){
27 s->base=(int*)realloc(s->base,(s->stacksize+STACKINCREMENT)*sizeof(int));
28 if(!s->base) exit(1);
29 s->top=s->base+s->stacksize;
30 s->stacksize+=STACKINCREMENT;
31 }
32 *s->top++=e;
33 return 0;
34 }
35 int Pop(SqStack* s)
36 {
37 if(s->top==s->base) exit(1);
38 return *(-- s->top);
39 }
40 int main()
41 {
42 SqStack s;
43 InitStack(&s);
44 int i=0;
45 while(i++<10)
46 {
47 Push(&s,i);
48 }
49 printf("top=%d\n",Pop(&s));
50 return 0;
51 }
队列:一种先进先出(FIFO)的线性表,只允许在队头删除,在队尾插入。
链式结构的队列实现代码:
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<stdlib.h>
4 typedef struct QNode{
5 int data;
6 struct QNode *next;
7 }QNode,*QueuePtr;
8 typedef struct {
9 QueuePtr front;
10 QueuePtr rear;
11 }LinkQueue;
12 int InitQueue(LinkQueue *Q)
13 {
14 Q->front=Q->rear=(QueuePtr)malloc(sizeof(QNode));
15 if(!Q->front) exit(1);
16 Q->front->next=NULL;
17 return 0;
18 }
19 int DestoryQueue(LinkQueue *Q)
20 {
21 while(Q->front)
22 {
23 Q->rear=Q->front->next;
24 free(Q->front);
25 Q->front=Q->rear;
26 }
27 return 0;
28 }
29 int EnQueue(LinkQueue *Q,int e)
30 {
31 QueuePtr p=(QueuePtr)malloc(sizeof(QNode));
32 if(!p) exit(1);
33 p->data=e;
34 p->next=NULL;
35 Q->rear->next=p;
36 Q->rear=p;
37 return 1;
38 }
39 int DeQueue(LinkQueue *Q)
40 {
41 QueuePtr p=Q->front->next;
42 if(Q->rear==Q->front) return 1;
43 Q->front->next=p->next;
44 if(p==Q->rear) Q->rear=Q->front;
45 free(p);
46 return 0;
47 }
48
49 int main()
50 {
51 int e;
52 LinkQueue Q;
53 printf("input value:");
54 scanf("%d",&e);
55 InitQueue(&Q);
56 EnQueue(&Q,e);
57 printf("%d %d\n",Q.front->next->data,Q.rear->data);
58 return 0;
59 }
插入排序--直接插入排序:
基本思想:
将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增 1 的有序表。即:
先将序列的第 1 个记录看成是一个有序的子序列,然后从第 2 个记录逐个进行插入,
直至整个序列有序为止。
要点:设立哨兵,作为临时存储和判断数组边界之用。
1 #include<stdio.h>
2 void InserSort(int *a,int length)
3 {
4 int j=0,i=0,tmp=0;
5 for(i=1;i<length;i++)
6 {
7 if(a[i]<a[i-1])
8 | { |
9 | tmp=a[i]; |
10 | j=i-1; |
11 | for(j;tmp<a[j]&&j>=0;j--) |
12 | { |
13 | a[j+1]=a[j]; |
14 | } |
15 | a[j+1]=tmp; |
16 | } |
17 | } |
18 19 } 20 int |
main() |
21 | { |
22 | int a[14]={56,23,23,24,42,23,24,67,23,12,5,89,24,4}; |
23 | int i=0; |
24 | InserSort(a,14); |
25 | while(i<14) |
26 | { |
27 | printf("%d\t",a[i]); |
28 | i++; |
29 | } |
30 | printf("\n"); |
31 | return 0; |
32 | } |
插入排序--折半插入排序
折半插入排序仅是减少关键字间的比较次数,而记录的移动次数不变,最终是靠直接插入排
序实现
1 #include<stdio.h>
2 void InserSort(int *a,int length)
3 {
4 int j=0,i=0,tmp=0;
5 for(i=1;i<length;i++)
6 {
7 tmp=a[i];
8 int high=i-1,low=0,m=0;
9 while(low<=high)
10 {
11 | m=(high+low)/2; |
12 | if(tmp<a[m]) |
13 | { |
14 | high=m-1; |
15 | } |
16 | else{ |
17 | low=m+1; |
18 | } |
19 | } |
20 | for(j=i-1;j>high;j--) |
21 | { |
22 | a[j+1]=a[j]; |
23 | } |
24 | a[high+1]=tmp; |
25 26 27 |
} |
28 29 } 30 int |
main() |
31 | { |
32 | int a[14]={56,23,23,24,42,23,24,67,23,12,5,89,24,4}; |
33 | int i=0; |
34 | InserSort(a,14); |
35 | while(i<14) |
36 | { |
37 | printf("%d\t",a[i]); |
38 | i++; |
39 | } |
40 | printf("\n"); |
41 | return 0; |
42 | } |
插入排序--希尔排序:
希尔排序是 1959 年由 D.L.Shell 提出来的,相对直接排序有较大的改进。希尔排序又叫缩
小增量排序
基本思想:
先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记
录“基本有序”时,再对全体记录进行依次直接插入排序。
操作方法:
选择一个增量序列 t1,t2,…,tk,其中 ti>tj,tk=1;
按增量序列个数 k,对序列进行 k 趟排序;
每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表
进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序
列的长度。
实现代码:
1 #include<stdio.h>
2 void ShellInsert(int *a,int length,int dk)
3 {
4 int i=0,j=0;
5 for(i=dk;i<length;i++)
6 {
7 | if(a[i]<a[i-dk]) |
8 | { |
9 | int tmp=a[i]; |
10 | j=i-dk; |
11 | for(j;tmp<a[j]&&j>=0;j=j-dk) |
12 | { |
13 | a[j+dk]=a[j]; |
14 | } |
15 | a[j+dk]=tmp; |
16 }
17 }
18 }
19 void ShellSort(int *a,int length)
20 {
21 int dk=length/2;
22 while(dk>0)
23 {
24 ShellInsert(a,length,dk);
25 dk=dk/2;
26 }
27 }
28 int main()
29 {
30 int a[14]={56,23,23,24,42,23,24,67,23,12,5,89,24,4};
31 int i=0;
32 ShellSort(a,14);
33 while(i<14)
34 {
35 printf("%d\t",a[i]);
36 i++;
37 }
38 printf("\n");
39 return 0;
40 }
交换排序--冒泡排序:
1 #include<stdio.h>
2 void BubbleSort(int *a,int length)
3 {
4 int i=0,j=0;
5 for(i=0;i<length;i++)
6 {
7 | for(j=1;j<length-i;j++) |
8 | { |
9 | if(a[j]<a[j-1]) |
10 | { |
11 | int tmp=a[j]; |
12 | a[j]=a[j-1]; |
13 | a[j-1]=tmp; |
14 | } |
15 | } |
16 | } |
17 } 18 int |
main() |
19 | { |
20 | int a[14]={56,23,23,24,42,23,24,67,23,12,5,89,24,4}; |
21 | int i=0; |
22 | BubbleSort(a,14); |
23 | while(i<14) |
24 | { |
25 | printf("%d\t",a[i]); |
26 | i++; |
27 | } |
28 | printf("\n"); |
29 | return 0; |
30 | } |
冒泡排序算法的改进:
对冒泡排序常见的改进方法是加入一标志性变量 exchange,用于标志某一趟排序过程中是否
有数据交换,如果进行某一趟排序时并没有进行数据交换,则说明数据已经按要求排列好,
可立即结束排序,避免不必要的比较过程。本文再提供以下两种改进算法:
1.设置一标志性变量 pos,用于记录每趟排序中最后一次进行交换的位置。由于 pos 位置之
后的记录均已交换到位,故在进行下一趟排序时只要扫描到 pos 位置即可。
改进后算法如下:
void Bubble_1 ( int r[], int n) {
int i= n -1; //初始时,最后位置保持不变
while ( i> 0) {
int pos= 0; //每趟开始时,无记录交换
for (int j= 0; j< i; j++)
if (r[j]> r[j+1]) {
pos= j; //记录交换的位置
int tmp = r[j]; r[j]=r[j+1];r[j+1]=tmp;
}
i= pos; //为下一趟排序作准备
}
} 2
.传统冒泡排序中每一趟排序操作只能找到一个最大值或最小值,我们考虑利用在每趟排序
中进行正向和反向两遍冒泡的方法一次可以得到两个最终值(最大者和最小者) , 从而使排
序趟数几乎减少了一半。
void Bubble_2 ( int r[], int n){
int low = 0;
int high= n -1; //设置变量的初始值
int tmp,j;
while (low < high) {
for (j= low; j< high; ++j) //正向冒泡,找到最大者
if (r[j]> r[j+1]) {
tmp = r[j]; r[j]=r[j+1];r[j+1]=tmp;
}
--high; | //修改 high 值, 前移一位 |
for ( j=high; j>low; --j) //反向冒泡,找到最小者 | |
if (r[j]<r[j-1]) { | |
tmp = r[j]; r[j]=r[j-1];r[j-1]=tmp; | |
} |
++low; | //修改 low 值,后移一位 |
} | |
} |
交换排序--快速排序
基本思想:
1)选择一个基准元素,通常选择第一个元素或者最后一个元素,
2)通过一趟排序讲待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准
元素值小。另一部分记录的 元素值比基准值大。
3)此时基准元素在其排好序后的正确位置
4)然后分别对这两部分记录用同样的方法继续进行排序,直到整个序列有序。
1 #include<stdio.h>
2 int Partition(int *a,int low,int high)
3 {
4 int tmp=a[low];
5 while(low<high)
6 {
7 | while(low<high&&tmp<=a[high]) |
8 | high--; |
9 | a[low]=a[high]; |
10 | while(low<high&&tmp>=a[low]) |
11 | low++; |
12 | a[high]=a[low]; |
13 }
14 a[low]=tmp;
15 return low;
16 }
17 void QSort(int *a,int low,int high)
18 {
19 if(low<high)
20 {
21 int tmp=Partition(a,low,high);
22 QSort(a,low,tmp-1);
23 QSort(a,tmp+1,high);
24 }
25 }
26 void QuickSort(int *a,int length)
27 {
28 QSort(a,0,length-1);
29 }
30 int main()
31 {
32 int a[14]={56,23,23,24,42,23,24,67,23,12,5,89,24,4};
33 int i=0;
34 QuickSort(a,14);
35 while(i<14)
36 {
37 printf("%d\t",a[i]);
38 i++;
39 }
40 printf("\n");
41 return 0;
42 }
选择排序--简单选择排序
基本思想:
在要排序的一组数中,选出最小(或者最大)的一个数与第 1 个位置的数交换;然后在剩下
的数当中再找最小(或者最大)的与第 2 个位置的数交换,依次类推,直到第 n-1 个元素(倒
数第二个数)和第 n 个元素(最后一个数)比较为止。
1 #include<stdio.h>
2 int SelectMinKey(int *a,int length,int i)
3 {
4 int j=i;
5 for(i=i+1;i<length;i++)
6 {
7 | if(a[i]<a[j]) |
8 | { |
9 | j=i; |
10 }
11 }
12 return j;
13
14 }
15 void SelectSort(int *a,int length)
16 {
17 int i;
18 for(i=0;i<length;i++)
19 {
20 int j=SelectMinKey(a,length,i);
21 int tmp=a[i];
22 a[i]=a[j];
23 a[j]=tmp;
24 }
25 }
26 int main()
27 {
28 int a[14]={56,23,23,24,42,23,24,67,23,12,5,89,24,4};
29 int i=0;
30 SelectSort(a,14);
31 while(i<14)
32 {
33 printf("%d\t",a[i]);
34 i++;
35 }
36 printf("\n");
37 return 0;
38 }