一、线性表
1.概念:由n(n>=0)个相同类型数据元素组成,并且可以在任意位置进行插入和删除操作的有限序列。
2.分类:
今天,我们主要看一看顺序表中的静态顺序表,在后面的博客中,我会将动态顺序表的实现,以及动态、静态顺序表之间的区别做以总结,还有三种链表的简单实现,以及两种线性表的区别于联系做以总结。
二、静态顺序表
1.定义结构体:
typedef int DataType;
#define N 10
typedef struct SeqList
{
DataType _a[N];
size_t _size;
}SeqList;
2.实现的接口
void SeqListInit(SeqList* pSeq);//初始化
void SeqListPrint(SeqList* pSeq);//打印
void SeqListPushBack(SeqList* pSeq, DataType x);//尾插
void SeqListPushFront(SeqList* pSeq, DataType x);//头插
void SeqListPopFront(SeqList* pSeq);//头删
void SeqListPopBack(SeqList* pSeq);//尾删
void SeqListInsert(SeqList* pSeq, size_t pos, DataType x);//任意位置pos的插入
void SeqListErase(SeqList* pSeq, size_t pos);//任意位置的删除
int SeqListFind(SeqList* pSeq, DataType x);//查找
void SeqListModify(SeqList* pSeq, size_t pos, DataType x);//修改pos位置的元素
void SeqListRemove(SeqList* pSeq, DataType x);//删除x FIND+ERASE
void SeqListRemoveAll(SeqList* pSeq, DataType x);//将所有的x删掉
void SeqListBubbleSort(SeqList* pSeq);//冒泡排序
void SeqListSelectSort(SeqList* pSeq);//选择排序
void SeqListBinarySearch(SeqList* pSeq, DataType x);//二分查找
void Swap(DataType* l, DataType* r);//交换
3.具体实现
void SeqListInit(SeqList* pSeq)
{
memset(pSeq->_a, 0, sizeof(DataType)*N);
pSeq->_size = 0;
}
void SeqListPrint(SeqList* pSeq)
{
size_t i = 0;
for (i = 0; i < pSeq->_size; ++i)
{
printf("%d", pSeq->_a[i]);
}
printf("\n");
}
//防御式编程,如果传入的是指针变量,而且不能为空,需要用断言
void SeqListPushBack(SeqList* pSeq, DataType x)
{
assert(pSeq);
if (pSeq->_size >= N)
{
printf("SeqList is full!\n");
return;
}
else
{
pSeq->_a[pSeq->_size] = x;//数组是用下标存储的,这里不需要加减一操作
pSeq->_size++;
}
}
//头插时需要将所有的数据往后挪
void SeqListPushFront(SeqList* pSeq, DataType x)
{
assert(pSeq);
if (pSeq->_size >= N)
{
printf("SeqList is full!\n");
return;
}
else
{
int end = pSeq->_size - 1;
while (end >= 0)
{
pSeq->_a[end + 1] = pSeq->_a[end];
--end;
}
}
pSeq->_a[0] = x;
pSeq->_size++;
}
void SeqListPopFront(SeqList* pSeq)
{
/*assert(pSeq);
if (pSeq->_size == 0)
{
printf("SeqList is empty!\n");
return;
}
else
{
size_t i = 1;
for (; i < pSeq->_size; ++i)
{
pSeq->_a[i-1] = pSeq->_a[i];
}
pSeq->_size--;
}*/
SeqListErase(pSeq, 0);
}
void SeqListPopBack(SeqList* pSeq)
{
assert(pSeq);
if (pSeq->_size == 0)
{
printf("SeqList is empty!\n");
return;
}
else
{
pSeq->_a[pSeq->_size - 1] = 0;//这里的操作可以不要,注意类型
pSeq->_size--;
}
}
void SeqListInsert(SeqList* pSeq, size_t pos, DataType x)
{
assert(pSeq);
if (pSeq->_size >= N)
{
printf("SeqList is full!\n");
return;
}
else
{
//end->-1 pos->0 条件居然为真,为什么?类型提升。当两个类型不一样的时候会像类型大的提升
//end为有符号 pos 为无符号 都会向无符号转 隐式的类型提升
//方法一:pos改为int 类型
int end = pSeq->_size - 1;
for (; end > (int)pos;)//方法二:
{
pSeq->_a[end + 1] = pSeq->_a[end];
--end;
}
pSeq->_a[pos] = x;
pSeq->_size++;
}
}
void SeqListErase(SeqList* pSeq, size_t pos)
{
assert(pSeq);
assert(pos < pSeq->_size);
if (pSeq->_size == 0)
{
printf("SeqList is empty!\n");
}
else
{
int i = pos;
while (i < pSeq->_size - 1)
{
pSeq->_a[i] = pSeq->_a[i + 1];
pSeq->_size--;
}
}
}
int SeqListFind(SeqList* pSeq, DataType x)
{
assert(pSeq);
int i = 0;
for (; i < pSeq->_size; ++i)
{
if (pSeq->_a[i] == x)
{
return i;
}
}
return -1;
}
void SeqListModify(SeqList* pSeq, size_t pos, DataType x)
{
assert(pSeq&&pos < pSeq->_size);
pSeq->_a[pos] = x;
}
//1 2 5 6 4 2 2 0 9 删除所有的2
void SeqListRemoveAll(SeqList* pSeq, DataType x)
{
assert(pSeq);
size_t index = 0;
size_t i = 0;
size_t count = 0;
for (; i < pSeq->_size; ++i)
{
if (pSeq->_a[i] != x)
{
pSeq->_a[index] = pSeq->_a[i];
index++;
}
else
{
count++;
}
}
pSeq->_size -= count;
}
void SeqListBubbleSort(SeqList* pSeq)
{
assert(pSeq);
int i = 1;
int end = pSeq->_size;
while (end > 1)
{
int exchange = 0;
for (; i < pSeq->_size; ++i)
{
if (pSeq->_a[i - 1]>pSeq->_a[i])
{
Swap(&pSeq->_a[i - 1], &pSeq->_a[i]);
exchange = 1;
}
}
if (exchange == 0)
{
break;
}
--end;
}
}
void Swap(DataType* l, DataType* r)
{
DataType tmp = *l;
*l = *r;
*r = tmp;
}
void SeqListSelectSort(SeqList* pSeq)
{
int left = 0;
int right = pSeq->_size - 1;
while (left < right)
{
int max = left;
int min = left;
int i = 0;
while (i <= right)
{
if (pSeq->_a[i]>pSeq->_a[max])
max = i;
if (pSeq->_a[i] < pSeq->_a[min])
min = i;
++i;
}
Swap(pSeq->_a[left], pSeq->_a[min]);
if (left == max)
max = min;
Swap(pSeq->_a[right], pSeq->_a[max]);
++left;
--right;
}
}
//[]
//[)
void SeqListBinarySearch(SeqList* pSeq,DataType x)
{
assert(pSeq);
int left = 0;
int right = pSeq->_size - 1;
int mid = left + (right - left) >> 1;
/*while (left <= right)
{
if (pSeq->_a[mid] < x)
{
left = mid + 1;
}
else if (pSeq->_a[mid]>x)
{
right = mid - 1;
}
else
{
return mid;
}*/
while (left<right)
{
if (pSeq->_a[mid] < x)
{
left = mid + 1;
}
else if (pSeq->_a[mid] < x)
{
right = mid;
}
else
{
return mid;
}
}
return -1;
}
4.部分测试用例
void Text1()
{
SeqList s;
SeqListInit(&s);
SeqListPushBack(&s, 1);
SeqListPushBack(&s, 2);
SeqListPushBack(&s, 3);
SeqListPushBack(&s, 4);
SeqListPrint(&s);
SeqListPushFront(&s, 4);
SeqListPushFront(&s, 3);
SeqListPushFront(&s, 2);
SeqListPushFront(&s, 1);
SeqListPrint(&s);
SeqListPopBack(&s);
SeqListPopBack(&s);
SeqListPopBack(&s);
SeqListPopFront(&s);
SeqListPrint(&s);
SeqListInsert(&s, 0, 20);
SeqListErase(&s, 0);
}