简单描述
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
顺序表一般可以分为:
静态顺序表:使用定长的数组存储。
动态顺序表:使用动态开辟的数组存储。
// 顺序表的静态存储
#define N 100
typedef int SLDataType;
typedef struct SeqList
{
SLDataType array[N]; // 定长数组
size_t size; // 有效数据的个数
}SeqList;
// 顺序表的动态存储
typedef struct SeqList
{
SLDataType* array; // 指向动态开辟的数组
size_t size ; // 有效数据个数
size_t capicity ; // 容量空间的大小
}SeqList;
主要操作
1、初始化顺序表
2、顺序表尾插、尾删
3、顺序表头插、头删
4、顺序表任意位置插入、任意位置删除
5、顺序表元素查找
6、删除顺序表中第一个值为x的元素
7、删除顺序表中所有值为x的元素
8、修改顺序表中某一元素的数值
9、顺序表扩容,销毁及打印
10、对顺序表实现BinaryFind(二分查找)
11、对顺序表实现InsertSort(插入排序)
12、对顺序表实现BubbleSort(冒泡排序)
下面是具体操作:
初始化顺序表
//初始化
void SeqListInit(PSeq ps1, int newcapicity)
{
assert(ps1);
assert(newcapicity != 0);
ps1->arr = (SLDataType*)malloc(sizeof(int)*newcapicity);
assert(ps1->arr);
ps1->capicity = newcapicity;
ps1->size = 0;
}
销毁顺序表
//销毁
void SeqListDestory(PSeq ps1)
{
if (ps1->arr)
{
free(ps1->arr);
ps1->arr = NULL;
ps1->capicity = 0;
ps1->size = 0;
}
}
顺序表扩容
//数据扩容
void CheckCapaticity(PSeq ps1)
{
assert(ps1);
if (ps1->capicity==ps1->size)
{
ps1->capicity *= 2;
realloc(ps1->arr, sizeof(SLDataType)*ps1->capicity);
}
}
打印顺序表
//打印输出
void SeqListPrint(PSeq ps1)
{
assert(ps1);
int i = 0;
for (int i = 0; i< (ps1->size); ++i)
{
printf("%d ", ps1->arr[i]);
}
printf("\n");
}
顺序表从尾部插入
//尾插
void SeqListPushBack(PSeq ps1, SLDataType x)
{
assert(ps1);
CheckCapaticity(ps1);
ps1->arr[ps1->size] = x;
ps1->size++;
}
顺序表从头部插入
//头插
void SeqListPushFront(PSeq ps1, SLDataType x)
{
assert(ps1);
CheckCapaticity(ps1);
int i = 0;
for (i = (ps1->size);i>0; --i)
{
ps1->arr[i] = ps1->arr[i - 1];
}
ps1->arr[0] = x;
ps1->size++;
}
顺序表从任意位置插入
//任意pos位置的插入
void SeqListInsert(PSeq ps1, int pos, SLDataType x)
{
assert(ps1);
assert(pos >= 0 && pos <= ps1->size);
CheckCapaticity(ps1);
int i = 0;
for (i = (ps1->size); i > pos;i--)
{
ps1->arr[i] = ps1->arr[i-1];
}
ps1->arr[pos] = x;
ps1->size++;
}
顺序表从尾部删除
//尾删
void SeqListPopBack(PSeq ps1)
{
assert(ps1);
assert(ps1->size > 0);
ps1->size--;
}
顺序表从头部删除
//头删
void SeqListPopFront(PSeq ps1)
{
assert(ps1);
assert(ps1->size > 0);
int i = 0;
for (i = 1; i<ps1->size;i++)
{
ps1->arr[i-1] = ps1->arr[i];
}
ps1->size--;
}
顺序表从任意位置删除
//删除pos位的元素
void SeqListErase(PSeq ps1, int pos)
{
assert(ps1);
assert(pos <= ps1->size && pos >= 0);
int i = 0;
for (i = pos+1; i<=ps1->size;i++)
{
ps1->arr[i - 1] = ps1->arr[i];
}
ps1->size--;
}
顺序表查找某一元素的节点,并返回下标
//查值为x的节点,并返回下标
int SeqListFind(PSeq ps1, SLDataType x)
{
assert(ps1);
int i = 0;
for (i = 0; i <ps1->size;i++)
{
if (ps1->arr[i]==x)
{
return i;
}
}
return -1;
}
顺序表删除第一个元素为某值的节点
//删除第一个值为x的节点
void SeqListRemove(PSeq ps1, SLDataType x)
{
assert(ps1);
int ret=SeqListFind(ps1, x);
if (ret != -1)
{
SeqListErase(ps1, ret);
}
}
顺序表删除所有元素为某值的节点
//删除所有值为x的节点
//设置中间变量tem重复利用SeqlistFind与SeqlistErase函数
void SeqListRemoveAll(PSeq ps1, SLDataType x)
{
assert(ps1);
int tem = -1;
while ((tem=SeqListFind(ps1,x))!=-1)
{
SeqListErase(ps1, tem);
}
}
顺序表修改某一元素数值
//修改第POS位的值
void SeqListModify(PSeq ps1, int pos, SLDataType x)
{
assert(ps1);
//assert((pos >= 0) && pos < (ps1->size));
int i = 0;
for (int i = 0; i < ps1->size;i++)
{
if (i==pos)
{
ps1->arr[i] = x;
}
}
}
对顺序表实现BubbleSort(插入排序)
//对顺序表实现BubbleSort
void SeqListBubbleSort(PSeq ps1)
{
assert(ps1);
int i = 0;
int j = 0;
for (i = 0; i < (ps1->size);i++)
{
int flag = 1;
for (j = 0; j <(ps1->size-1-i);j++)
{
if ((ps1->arr[j]) > (ps1->arr[j+1]))
{
int ret = 0;
ret = ps1->arr[j];
ps1->arr[j] = ps1->arr[j+1];
ps1->arr[j+1] = ret;
flag = 0;
}
}
if (flag==1)
{
return;
}
}
}
对顺序表实现BinaryFind(二分查找)
//对顺序表实现BinaryFind(二分查找) 仅限于排序后的序列
int SeqListBinaryFind(PSeq psl, SLDataType x)
{
assert(psl);
assert(psl->size >= 2);
int left = 0;
int right = psl->size - 1;
while (left<right)
{
int mid = left + (right - left) / 2;
if (psl->arr[mid]>x)
{
right = mid - 1;
}
else if (psl->arr[mid] < x)
{
left = mid + 1;
}
else
return mid+1;
}
return -1;
}
对顺序表实现BubbleSort(冒泡排序)
//插入排序代码优化
void InsertSort(PSeq ps1)
{
assert(ps1);
int i = 0;
for (i = 0; i < ps1->size-1; i++)
{
int right = i;
int tmp = ps1->arr[right+1];
while((right>=0) && ((ps1->arr[right])>tmp))
{
ps1->arr[right+1]=ps1->arr[right];
right--;
}
ps1->arr[right+1] = tmp;
}
}
实战例子
题目要求
(1)完成顺序表的基本运算:初始化、显示、求长度、判空、判满、插入、删除、按位置取元素、按值查找等,并编写主函数测试算法。
(2))设计算法:将一个元素插入到有序的顺序表中,使顺序表仍有序,并编写主函数测试算法。
(3)设A和B两个顺序表,其元素按从小到大的顺序排列。编写一个算法将A和B的全部元素合并到有序顺序表C中,并编写主函数测试算法。
算法代码
#include <stdio.h>
#include <stdlib.h>
#define Size 5
typedef struct Table {
int* head;
int length;
int size;
}table;
//初始化函数
table initTable() {
table t;
t.head = (int*)malloc(Size * sizeof(int));
if (!t.head)
{
printf("初始化失败\n");
exit(0);
}
t.length = 0;
t.size = Size;
return t;
}
//求长度
int TableLength(table t) {
return t.length;
}
//判空函数
int emptyTable(table t) {
if (!t.length)
return 1;
return 0;
}
//判满
int fullTable(table t) {
int temp = 0;
if (t.length == t.size)
temp = 1;
return temp;
}
//插入函数,其中,elem为插入的元素,add为插入到顺序表的位置
table addTable(table t, int elem, int add)
{
//判断插入本身是否存在问题
if (add > t.length + 1 || add < 1) {
printf("插入位置有问题\n");
return t;
}
//判断是否需要申请内存空间
if (fullTable(t)) {
t.head = (int*)realloc(t.head, (t.size + 1) * sizeof(int));
if (!t.head) {
printf("存储分配失败\n");
return t;
}
t.size++;
}
//后移操作
for (int i = t.length - 1; i >= add - 1; i--) {
t.head[i + 1] = t.head[i];
}
//将所需插入元素,添加到顺序表的相应位置
t.head[add - 1] = elem;
t.length++;
return t;
}
//按顺序插入,找插入位置
table insertTable(table t, int elem) {
int i = 0;
while (i < t.length && elem >= t.head[i])//从小到大排列
{
i++;//注意i从0开始的 ,所以后面不用i - 1 ,这里的i即为下标
}
t = addTable(t, elem, ++i);
return t;
}
table mergeTable(table t1, table t2, table t3) {
int i = 0, j = 0, k = 0;
while (i < t1.length || j < t2.length) {
if (j == t2.length || i < t1.length && t1.head[i] < t2.head[j])
t3.head[k++] = t1.head[i++];
else
t3.head[k++] = t2.head[j++];
}
t3.length = k;
return t3;
}
table delTable(table t, int add) {
if (add > t.length || add < 1) {
printf("被删除元素的位置有误\n");
return t;
}
//删除操作
for (int i = add; i < t.length; i++) {
t.head[i - 1] = t.head[i];
}
t.length--;
return t;
}
//按值查找函数,其中,elem表示要查找的数据元素的值
int selectTable(table t, int elem) {
for (int i = 0; i < t.length; i++) {
if (t.head[i] == elem) {
return i + 1;
}
}
return -1;//如果查找失败,返回-1
}
//按位置取元素
int getTable(table t, int add) {
if (add > t.length || add < 1) {
printf("被查找元素的位置有误\n");
return 0;
}
return t.head[add - 1];
}
//更改函数,其中,elem为要更改的元素,newElem为新的数据元素
table amendTable(table t, int elem, int newElem) {
int add = selectTable(t, elem);
t.head[add - 1] = newElem;
//由于返回的是元素在顺序表中的位置,所以-1就是该元素在数组中的下标
return t;
}
void displayTable(table t) {
for (int i = 0; i < t.length; i++) {
printf("%d ", t.head[i]);
}
printf("\n");
}
int main() {
int i, add = 0, elem = 0;
table t1 = initTable();
//初始化后赋值
for (i = 1; i <= Size; i++) {
t1.head[i - 1] = i;
t1.length++;
}
printf("原顺序表:\n");
displayTable(t1);
printf("当前顺序表长度为:%d\n", TableLength(t1));
if (fullTable(t1)) {
printf("当前顺序表已满\n");
}
printf("\n");
//删除指定元素
printf("请输入要删除的元素:");
scanf_s("%d", &elem);
t1 = delTable(t1, elem);
printf("删除%d元素后,顺序表为:", elem);
displayTable(t1);
printf("\n");
//按位置插入元素
printf("请输入要插入元素的位置和元素的值:");
scanf_s("%d %d", &add, &elem);
printf("在第%d的位置插入元素%d后,顺序表为:\n", add, elem);
t1 = addTable(t1, elem, add);
displayTable(t1);
printf("\n");
//查找元素的位置
printf("请输入要查找元素的值:");
scanf_s("%d", &elem);
printf("查找元素%d的位置为:\n", elem);
add = selectTable(t1, elem);
printf("%d\n", add);
//修改元素的值
printf("请输入要修改的元素:");
scanf_s("%d", &elem);
printf("请输入修改后的值:");
scanf_s("%d", &add);
printf("将元素%d改为%d:\n", elem, add);
t1 = amendTable(t1, elem, add);
displayTable(t1);
printf("\n");
//按位置查找元素
printf("请输入要查找元素的位置:\n");
scanf_s("%d", &add);
printf("位置%d的元素为:", add);
printf("%d\n", getTable(t1, add));
//有序顺序表的插入
printf("有序顺序表如下\n");
t1.length = 0;
for (i = 1; i <= Size; i++) {
t1.head[i - 1] = i;
t1.length++;
}
displayTable(t1);
printf("请输入要插入的元素值:\n");
scanf_s("%d", &elem);
t1 = insertTable(t1, elem);
displayTable(t1);
//有序顺序表的合并
t1.length = 0;
for (i = 1; i <= t1.size; i++) {
t1.head[i - 1] = i;
t1.length++;
}
printf("顺序表A的值为:\n");
displayTable(t1);//t1为A顺序表
table t2 = initTable();//t2为B顺序表
for (i = t1.head[t1.size - 1] + 1; i <= t1.size + 5; i++) {
t2.head[i - t1.head[t1.size - 1] - 1] = i;
t2.length++;
}
printf("顺序表B的值为:\n");
displayTable(t2);
table t3 = initTable(); //t3用来存放合并后的顺序表
t3 = mergeTable(t1, t2, t3);
printf("合并后的顺序表为:");
displayTable(t3);
return 0;
}