#pragma once
#include<stdio.h>
#include<assert.h>
#define MAX_SIZE 10
typedef int DataType;
typedef struct SeqList
{
DataType _array[MAX_SIZE];
int _size; //顺序表中有效元素的个数
}SeqList,*PSeqList;
静态顺序表的特点是顺序表中的元素个数是固定的,这里的MAX_SIZE等于10,就说明顺序表中最多存放10个数据。
//顺序表初始化
void SeqListInit(PSeqList ps)
{
if(ps)
ps->_size = 0;
}
顺序表初始化操作就是把顺序表中表示有效元素的个数的变量置为0
//顺序表尾插数据
void SeqListPushBack(PSeqList ps, DataType data)
{
if(NULL == ps)
{
return;
}
if(ps->_size == MAX_SIZE)
{
printf("顺序表已满\n");
return;
}
ps->_array[ps->_size] = data;
ps->_size++;
}
尾插操作要先判断顺序表是否存在,然后判断有效元素个数的数量是否达到MAX_SIZE,之后在顺序表尾部ps->size处插入数据data(下标比size少1,所以size即表示插入时所需的下标)
//顺序表尾删
void SeqListPopback(PSeqList ps)
{
if(NULL == ps)
return;
if(0 == ps->_size)
{
printf("顺序表已空\n");
return;
}
ps->_array[ps->_size-1] = 0;
--ps->_size;
}
尾删操作先判断顺序表是否存在,再判断顺序表是否为空(为空直接返回)
//顺序表头插数据
void SeqListPushFront(PSeqList ps, DataType data)
{
int i = 0;
if(NULL == ps)
return;
if(MAX_SIZE == ps->_size)
{
printf("顺序表已满\n");
return;
}
for(i = ps->_size-1; i>=0;--i)
{
ps->_array[i+1] = ps->_array[i];
}
ps->_array[0] = data;
ps->_size++;
}
头插操作要先判断顺序表是否存在,然后判断有效元素个数的数量是否达到MAX_SIZE,先将前size个元素全部向后移动一位,留出下标为0的位置的空间将data放进去
//顺序表头删数据
void SeqListPopFront(PSeqList ps)
{
int i = 0;
if(NULL == ps)
return;
if(ps->_size == 0)
{
printf("顺序表已空\n");
return;
}
for(;i < ps->_size-1; i++)
{
ps->_array[i] = ps->_array[i+1];
}
ps->_size--;
}
头删开始和尾删相同,都先判断。然后将前size个元素全部向前移动一位(下标为0的元素被覆盖),完成头删操作
//显示顺序表中的数据个数
int SeqListSize(PSeqList ps)
{
if(NULL == ps)
{
printf("顺序表为空\n");
assert(0);
return 0;
}
return ps->_size;
}
先判空,不满足条件打印size
//打印顺序表
void PrintSeqList(PSeqList ps)
{
int i = 0;
if(NULL == ps)
{
return;
}
for(; i<ps->_size;++i)
printf("%d",ps->_array[i]);
printf("\n");
}
先判空,然后打印前size个元素
//任意位置插入
void SeqListInsert(PSeqList ps,int pos, DataType data)
{
int i = 0;
if(NULL == ps || !(pos>=0 && pos<= ps->_size))
{
return;
}
if(MAX_SIZE == ps->_size)
{
printf("顺序表已满,无法插入\n");
return;
}
for(i = ps->_size-1;i >= pos;--i)
{
ps->_array[i+1] = ps->_array[i];
}
ps->_array[pos] = data;
ps->_size++;
}
判断条件:顺序表是否存在,pos满足大于0且小于size,顺序表没有满。将从后往前数size-pos个元素向后移动留出下标为pos的位置的空间插入data
//任意位置的删除
void SeqListErase(PSeqList ps,int pos)
{
int i = pos;
if(NULL == ps || !(pos >= 0 && pos < ps->_size))
{
return;
}
if(0 == ps->_size)
{
printf("顺序表已空,无法删除\n");
return;
}
for(; i < ps->_size-1;i++)
{
ps->_array[i] = ps->_array[i+1];
}
ps->_size--;
}
判断条件:顺序表是否存在,pos大于0且pos小于size,顺序表是否为空。将从后往前size-pos个元素全部向前移动一位(下标为pos的元素被覆盖),完成删除操作
// 在顺序表中查找值为第一个data的元素,找到返回该元素在顺序表中的位置,否则返回-1
int SeqListFind(PSeqList ps,DataType data)
{
int i = 0;
if(NULL == ps)
return;
for(i; i<ps->_size; ++i)
{
if(ps->_array[i] == data)
return i;
}
return -1;
}
从下标为0的元素开始找起,找到data元素返回其下标,没找到返回-1
// 移除顺序表中第一个值为data的元素
void Remove(PSeqList ps, DataType data)
{
SeqListErase(ps,SeqListFind(ps,data));
}
使用函数SeqListFind(查找元素)和SeqListErase(删除任意位置的元素)实现该操作
// 移除顺序表中所有值为data的元素
void RemoveALL(PSeqList ps, DataType data)
{
int count = 0;
int i = 0;
for(; i< ps->_size; ++i)
{
if(ps->_array[i] == data)
count++;
else
ps ->_array[i-count] = ps ->_array[i];
}
ps->_size -= count;
}
定义一个计数变量count,每当找到顺序表中对应的data元素时,count++,找到一个就需要把从后往前i-count个元素全部向前移动一位(当count改变且第一次执行else操作时的i-1为找到data元素的下标,i-count为所需移动的位数。例:第一次找到data时,count=1,每次向前移动一位,第二次找到data是count=2,从第二次找到data的下标i-1开始,每次向前移动两位)
void Swap(int* pLeft, int *pRight)
{
int temp = *pLeft;
*pLeft = *pRight;
*pRight = temp;
}
// 使用冒泡排序对顺序表中的元素进行排序
void BubbleSort(PSeqList ps)
{
int j = 0;
int i = 0;
int IsChange = 0;
for(; i< ps->_size-1 ;++i)
{
IsChange = 0;
for(; j< ps->_size-1-i;++j)
{
if(ps->_array[j] > ps ->_array[j+1])
{
Swap(&(ps->_array[j]),&(ps->_array[j+1]));
IsChange = 1;
}
}
if(!IsChange)
break;
}
}
Swap函数为辅助函数,作用是交换两个变量的值。
从下标为i的元素开始排序,把元素值较大的元素放在最后
IsChange变量的作用是,在第一趟冒泡的排序的时候,如果顺序表本来就有序,则无需进行后续的排序操作,循环直接退出
//选择排序
void SelectSort(PSeqList ps)
{
int i = 0;
int j = 0;
int maxPos = 0;
for(; i<ps->_size;++i)
{
maxPos = 0;
for(j=1; j< ps->_size - i; ++j)
{
if(ps->_array[j] > ps ->_array[maxPos])
maxPos = j;
}
if(maxPos != ps->_size -1 -i)
Swap(&ps->_array[maxPos],&ps->_array[ps->_size-1-i]);
}
}
标记最大元素的下标,一趟排序结束后和第size-1-i位置的元素做比较,将最大的元素放在此位置。
缺陷:只能从小到大排序。
优化方式:定义一个函数指针,用户自己决定选择排序方式。