存储结构:顺序存储和链式存储
算法设计的要求:
1.正确性 2.可读性 3.健壮性 4.时间效率高和存储量低
常用的时间复杂度:
o(1) < o(logn) < o(n) < o(nlogn) < o(n*n) < o(n*n*n) ...
线性表:零个或多个数据元素的有限序列。
第一个元素无前驱,最后一个元素无后继,其他元素都有且只有一个前驱和后继
线性表的顺序存储:(插入)------
Status ListInsert(SqList *L, int i, ElemType e)
{
int k;
if (L->length == MAXSIZE)
return error;
if (i < 1 || i > L->length + 1)
return error;
if (i < L->length)
{
for (k = L->length - 1; k >= i - 1; k--) //将要插入位置后数据元素向后移动一位
L->data[k + 1] = L->data[k];
}
L->data[i - 1] = e;
L->length++;
return OK;
}
Status ListDelete(Sqlist *L, int i, Element *e)
{
int k;
if (L->length == 0)
return error;
if (i < 1 || i > L->length)
return error;
*e = L->data[i - 1];
if (i < L->length)
{
for (k = i; k < L->length; k++)
L->data[k - 1] = L->data[k];
}
L->length--;
return OK;
}
顺序结构最大的缺点:插入和删除时需要移动大量的元素,比较耗费时间;
单链表的插入和删除:
Status ListInsert(LinkList L, int i, ElemType e)
{
int j;
LinkList p,s;
p = L;
j = 1;
while (p && j < i)
{
p = p->next;
++j;
}
if (!p || j > i)
return error;
/*有头指针
**在第i个节点中插入
s = (LinkList)malloc(sizeof(Node));
s->data = e;
s->next = p->next;
p->next = s;
*/
retun OK;
}
单链表的删除:删除第i个节点
Status ListDelete(LinkList *L, int i, ElemType *e)
{
int j;
LinkList p, q;
p = L;
j = 1;
while (p->next && j < i)
{
p = p->next;
++j;
}
if (!(p->next) || j > i)
return error;
q = p->next;
p->next = q->next;
*e = q->data;
free(q);
return OK;
}
单链表结构与顺序存储结构的优缺点:
存储方式:顺序存储的存储单元连续,单链表采用一组任意的存储单元;
时间性能:
查找:顺序存储O(1),单链表O(n)
插入和删除:顺序存储的时间为O(n), 单链表时间为O(1);
空间性能:顺序存储需要预先分配,分大了浪费,小了易溢出;
单链表不需要预分配,元素个数不受限制;
快速排序:
对数组{50,10,90,30,70,40,80,60,20}进行排序
/*对顺序表L快速排序*/
void QuickSort(SqList *L)
{
Qsort(L, 1, L->length);
}
/*对顺序表L中的字序列L->r[low..high]做快速排序*/
void Qsort(Sqlist *L, int low, int high)
{
int pivot;
if (low < high)
{
pivot = Partition(L, low, high); /*将L->r[low..high]一分为二,算出枢轴pivot*/
Qsort(L, low, pivot - 1); /*对低子表递归排序*/
Qsort(L, pivot + 1, high); /*对高子表递归排序*/
}
}
/*交换顺序表L中子表的记录,使枢轴记录到位,并返回其所在位置*/
/*此时在它之前(后)的记录均不大(小)于它*/
int Partition(SqList *L, int low, int high)
{
int pivotkey;
pivotkey = L->r[low]; /*用子表的第一个记录作枢轴记录*/
while (low < high) /*从表的两端交替向中间扫描*/
{
while (low < high && L->r[high] >= pivotkey)
high--;
swap(L, low, high); /*将比枢轴记录小的记录交换到低端*/
while (low < high && L-r[low] <= pivotkey)
low++;
swap(L, low, high); /*将比枢轴记录打的记录交换到高端*/
}
return low;
}
归并排序算法:
/*对顺序表做归并排序*/
void MergeSort(Sqlist *L)
{
Msort(L->r, L->r, 1, L->length);
}
/*将SR[s...t]归并排序为TR1[s...t]*/
void Msort(int SR[], int TR1[], int s, int t)
{
int m;
int TR2[MAXSIZE+1];
if (s == t)
TR1[s] = SR[s];
else
{
m = (s +t ) / 2; /*将SR[s..t]平分为SR[s..m]和SR[m+1..t]*/
Msort(SR, TR2, s, m); /*递归将SR[s..m]归并为有序的TR2[s..m]*/
Msort(SR, TR2, m+1, t); /*递归将SR[m+1..t]归并为有序的TR[m+1..t]*/
Merge(TR2, TR1, s, m, t); /*将TR2[s..m]和TR2[M+1..t]归并到TR1[s..t]*/
}
}
/*将有序的SR[i..m]和SR[m+1..n]归并为有序的TR[i..n]*/
void Merge(int SR[], int TR[], int i, int m, int n)
{
int j,k,l;
for (j = m + 1, k = i; i <= m && j <= n; k++) /*将SR中记录有小到大归并入TR*/
{
if (SR[i] < SR[j])
TR[k] = SR[i++];
else
TR[k] = SR[j++];
}
if (i <= m)
{
for (l = 0; l <= m - i; l++)
TR[k+1] = SR[i+1]; /*将剩余的SR[i..m]复制到TR*/
}
if (j <= n)
{
for (l = 0; l <= n - j;l++)
TR[k+1] = SR[j+1]; /*将剩余的SR[j..n]复制到TR*/
}
}
简单选择排序:通过n-i次关键字间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i个记录交换之。
/*对顺序表L做简单选择排序*/
void SelectSort(Sqlist *L)
{
int i,j,min;
for (i = 1; i <= L->length; i++)
{
min = i;
for (j = i + 1; j <= L->length; j++)
{
if (L->r[min] > L->r[j])
min = j;
}
if (i != min)
swap(L, i, min);
}
}