快速排序
时间复杂度 = O ( n l o g n ) O(nlogn) O(nlogn)
算法思想
~~~~ 快速排序采用了分治的思想,将问题分成多个部分进行求解。
基本思路
- 1.先从数列中取出一个数作为基准数。
- 2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
- 3.再对左右区间重复第二步,直到各区间只有一个数。
C语言代码实现快速排序
#include <stdio.h>
#include <stdlib.h>
void quickSort(int* arr, int start, int end);
int main(void) {
int arr[] = { 12,555,41,0,5,3,96,21,8,3,555,20,60 };
int len = 13;
quickSort(arr, 0, 12);
for (int i = 0; i < len; i++) {
printf("%d ", arr[i]);
}
}
void quickSort(int* arr, int start, int end)
{
if (start >= end)
return;
int i = start, j = end;
int temp = arr[start];
printf("\nthis is a function");
while (i < j)
{
while (j > i && arr[j] > temp)
j--;
arr[i] = arr[j];
while (i < j && arr[i] < temp)
i++;
arr[j] = arr[i];
j--;
}
arr[i] = temp;
quickSort(arr, start, i-1);
quickSort(arr, i+1, end);
}
汇编实现
#基于汇编语言实现快速排序算法
.data
array: .word 2,1,3,55,0,6,9,22,84
len: .word 8
space: .asciiz " "
.globl main
.text
main:
move $a0,$zero
lw $a1,len
jal quickSort
li $t1,0 #设置t1为0
lw $t2,len#设置t2的值为len
sll $t2,$t2,2
print_array:
lw $a0,array+0($t1) #加载t1地址所储存的值
li $v0,1 # 设置系统调用指令
syscall
la $a0,space #打印空白间隔
li $v0,4
syscall
addi $t1,$t1,4 #指令加4
bgt $t1,$t2,Done #打印结束结束程序
j print_array
quickSort: #void quickSort(int* arr, int start,int end) 这里将arr做全局变量
addi $sp,$sp,-16 #创建栈帧储存returnAdress
sw $ra,0($sp) #将调用quickSort函数的返回地址储存在栈帧顶部
sw $a0,4($sp) #将start 储存在栈帧中
sw $a1,8($sp) #将end 储存在栈帧中
bge $a0,$a1,return #if start>=end return
move $t0,$a0 #int i = startIndex
move $t1,$a1#int j = endIndex
sll $t0,$t0,2 # i = 4*i
sll $t1,$t1,2 # j = 4*j
lw $t2,array + 0($t0) #temp = array[i] i 为索引
# while loop
whileLoop:
bge $t0,$t1,breakLoop #if i >= j goto outside loop
while1:
ble $t1,$t0,out1 #if j<= i break
lw $t3,array+0($t1) #temp2 = array[j]
ble $t3,$t2,out1 # if array[j]<=temp break
addi $t1,$t1,-4 # j-=4,在索引上j-=1
j while1
out1:
sw $t3,array+0($t0) #array[i] = array[j]
while2:
bge $t0,$t1,out2 #if i>=j break
lw $t3,array+0($t0) #temp2 = array[i]
bge $t3,$t2,out2 #if arrat[i]>=temp break
addi $t0,$t0,4 #i+=1
j while2
out2:
sw $t3,array+0($t1) #array[j] = array[i]
addi $t1,$t1,-4 #j- -
j whileLoop
breakLoop:
sw $t2,array+0($t0) #array[i] = temp
#调用函数1
#将索引还原为int指针
srl $t0,$t0,2
srl $a0,$a0,2
sw $t0,12($sp) #将i作为现场信息储存在栈帧中
addi $t0,$t0,-1
move $a1,$t0 #将第二个参数赋值为i-1
jal quickSort #quick(start,i-1)
#恢复现场信息
lw $a1,8($sp) #恢复end
lw $t0,12($sp) #恢复i
#调用函数2
addi $t0,$t0,1 #i+=1
move $a0,$t0 #将第一个参数赋值为i+1
jal quickSort
return:
lw $ra 0($sp)#在栈顶取返回地址
addi $sp,$sp,16#将栈执政上移一个栈帧
jr $ra
#return
Done:
总结
~~~~~ 快速排序通过双指针交替的变换指针所在位置的值,为一个数找到一个正确的位置放置,并通过分治策略将该思想分散到各个小部分实现。
注意要点
~~~~~ 实现时需注意只让后面移动的指针在换值以后进行强制移动。
- ~~~~~ 没有进行强制移动,会使得程序进入死循环。
- ~~~~~ 进行两次强制移动,会使得程序不准确,即i指针可能处于j指针之后。