顺序表的使用
顺序表其实在生活中有很多的应用,比如各类东西的排序,查找某个特定的数据,删除某个数据等等,今天我就给大家展现几个比较常用的实现。
1.二分查找
算法:二分查找是设立了最左,最右和中间值,将中间值和要查找的那个数进行比较,依次去缩小那个数据的范围,从而找到那个数。
与普通查找不同的是二分查找的时间复杂度为O(logN),普通查找都要从头找一遍,时间复杂度为O(N);
而二分查找这种算法在生活中应用也比较广,效率会更高。
代码实现:
int SeqListBinaryFind(SeqList* ps, SLDataType x)
{
// [begin, end]
int begin = 0, end = ps->_size-1 ;
while (begin <= end)
{
int mid = (begin + end) / 2;
if (ps->_array[mid] < x)
{
begin = mid + 1;
}
else if (ps->_array[mid] > x)
{
end = mid - 1;
}
else
{
return mid;
}
}
return -1;
}
2.冒泡排序(稳定排序)
算法:这种排序方法是两两个进行比较将大(小)的向后(前)进行调整,而它的终止位置是在上次调整的最后一个位置,因为冒泡一次调整到最后的一定是最大(最小)的数,不需要每一次都调到最后。
void Swap(SLDataType* left, SLDataType* right)
{
SLDataType tmp = *left;
*left = *right;
*right = tmp;
}
void SeqListBubbleSort(SeqList* ps)
{
size_t i = 0;
size_t j = 0;
for (i = 0; i < ps->_size-1; ++i)
{
for (j = 0; j < ps->_size-1- i; ++j)
{
if (ps->_array[j] > ps->_array[j + 1])
{
Swap(&(ps->_array[j]),&(ps->_array[j + 1]));
}
}
}
}
上面算法会有一点问题是每次肯定都要去把所有数都比较一次,哪怕它已经是有序的了我们可以设一个标识符,如果已经有序了,就结束循环。
下面是优化的代码:
void SeqListBubbleSort(SeqList* ps)
{
assert(ps);
size_t finish = ps->_size - 1;
while (finish > 0)
{
int exchange = 0;
for (size_t i = 1; i <= finish; ++i)
{
if (ps->_array[i - 1] > ps->_array[i])
{
SLDataType tmp = ps->_array[i - 1];
ps->_array[i - 1] = ps->_array[i];
ps->_array[i] = tmp;
exchange = 1;
}
}
if (exchange == 0)
break;
--finish;
}
}
3.删除数组中某个数字
算法:我的思路是设两个变量(按下标),其中一个依次走,将他所在位置的数和要删除的数进行比较,如果不相等,那就将它赋值给此时的另一个变量的位置,从而达到删除的目的。其实这就和再建一个数组将删除了这个数字的一组数拷进去,只是现在不需要另开辟空间。
时间复杂度O(N),空间复杂度O(1);
代码实现:
void SeqListRemoveAll(SeqList* ps, SLDataType x)
{
size_t cur = 0;
size_t dst = 0;
while (cur < ps->_size)
{
if (ps->_array[cur] != x)
{
ps->_array[dst] = ps->_array[cur];
dst++;
}
cur++;
}
ps->_size = dst;
}