顺序表:动态增长的数组,头部和中间插入效率极低
优点:cpu高级缓存利用率高,很多算法最好用数组
头文件"seqlist.h"
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<windows.h>
#include<cstdio>
#include<malloc.h>
#include<assert.h>
#define SEQLIST_INIT_SIZE 8
#define INC_SIZE 3 //空间增量的大小,而非翻倍增加
typedef int EType; //此处int可以换为任意类型
typedef struct Seqlist
{
EType *base;
int capacity; //顺序表容量
int size; //表的大小
} Seqlist;
//实现以下功能
void show(); //打印菜单
int Check(Seqlist *list); //增加顺序表的容量
void InitSeqlist(Seqlist *list); //初始化顺序表
void showlist(Seqlist *list); //打印顺序表
void pushback(Seqlist *list, EType x); //尾插
void pushfront(Seqlist *list, EType x); //头插
void popback(Seqlist *list); //尾删
void popfront(Seqlist *list); //头删
void insertpos(Seqlist *list, int pos, EType x); //在顺序表选定下标位置插入数据
int find(Seqlist *list, EType key); //查找顺序表中元素key的下标
int length(Seqlist *list); //求顺序表长度
void deletepos(Seqlist *list, int pos); //删除顺序表中选定下标位置元素
void deleteval(Seqlist *list, int key); //删除顺序表中值为key的元素
void sort(Seqlist *list); //冒泡排序
void reverse(Seqlist *list); //逆置顺序表
void clear(Seqlist *list); //清除顺序表元素
void destroy(Seqlist *list); //销毁顺序表
void merge(Seqlist *lt, Seqlist *la, Seqlist *lb); //合并两个顺序表
源文件"seqlist.cpp"
#include"seqlist.h"
void show() //打印菜单
{
printf("*************************\n");
printf("1 .尾插\n3 .头插 \n");
printf("3 .打印\n4 .尾删 \n");
printf("5 .头删\n6 .指定插入 \n");
printf("7 .查询\n8 .测长度 \n");
printf("9 .根据指定位置删除 \n10.根据指定元素删除 \n");
printf("11.冒泡排序\n12.逆置 \n");
printf("13.清空\n14.合并两个顺序表 \n");
printf("0.退出程序\n");
printf("*************************\n");
printf("请选择:>>");
}
int Check(Seqlist *list) //增加顺序表的容量
{
EType *newbase = (EType*)realloc(list, sizeof(EType)*(list->capacity + INC_SIZE));
//重新分配内存空间
if (newbase == NULL)
{
printf("内存空间已满,无法再分配内存空间!\n");
return false;
}
list->base = newbase; //改变指针的指向
list->capacity += INC_SIZE;
return true;
}
void InitSeqlist(Seqlist *list) //初始化顺序表
{
list->base = (EType*)malloc(sizeof(EType)*SEQLIST_INIT_SIZE); //开辟空间初始化
assert(list->base != NULL);
list->capacity = SEQLIST_INIT_SIZE; //容量空间
list->size = 0;
}
void pushback(Seqlist *list, EType x) //尾插
{
if (list->size >= list->capacity && !Check(list))
{ //Inc(list)用来判断增加顺序表容量是否成功,只有在失败的情况下才会进入if语句中
printf("顺序表容量已满,无法再在表尾继续插入新元素!\n");
return;
}
list->base[list->size] = x;
list->size++;
}
void pushfront(Seqlist *list, EType x) //头插
{
if (list->size >= list->capacity && !Check(list))
{
printf("顺序表容量已满,无法再在表头插入新元素!\n");
return;
}
for (int i = list->size; i > 0; i--) //向后移动整个顺序表
list->base[i] = list->base[i - 1];
list->base[0] = x;
list->size++;
}
void showlist(Seqlist *list) //打印顺序表
{
for (int i = 0; i < list->size; i++)
printf("%d ", list->base[i]);
printf("\n");
}
void popback(Seqlist *list) //尾删
{
if (list->size == 0)
{
printf("顺序表已空,无法再在表尾删除元素!\n");
return;
}
list->size--; //顺序表的大小-1,即删除最后一个元素
}
void popfront(Seqlist *list) //头删
{
if (list->size == 0)
{
printf("顺序表已空,无法再在表头删除元素!\n");
return;
}
for (int i = 0; i < list->size - 1; i++) //顺序表向前覆盖
list->base[i] = list->base[i + 1];
list->size--; //删除最后一个位置
}
void insertpos(Seqlist *list, int pos, EType x) //在顺序表选定下标位置插入数据
{
if (pos<0 || pos>list->size) //下标在规定范围且不超出顺序表
{
printf("插入位置不合法,无法插入元素!\n");
return;
}
if (list->size >= list->capacity && !Check(list))
{
printf("顺序表容量已满,无法在插入新的元素!\n");
return;
}
for (int i = list->size; i > pos; i--) //类似头插
list->base[i] = list->base[i - 1];
list->base[pos] = x;
list->size++;
}
int find(Seqlist *list, EType key) //查找顺序表中元素key的下标
{
for (int i = 0; i < list->size; i++) //遍历一遍顺序表
{
if (list->base[i] == key)
return i;
}
return -1;
}
int length(Seqlist *list) //求顺序表长度
{
return list->size;
}
void deletepos(Seqlist *list, int pos) //删除顺序表中选定下标位置元素
{
if (pos < 0 || pos >= list->size)
{
printf("删除位置不合法,无法删除元素!\n");
return;
}
for (int i = pos; i < list->size - 1; i++) //类似头删
list->base[i] = list->base[i + 1];
list->size--;
}
void deleteval(Seqlist *list, int key) //删除顺序表中值为key的元素
{
int pos = find(list, key);
if (pos == -1)
{
printf("顺序表中没有这个元素!\n");
return;
}
deletepos(list, pos);
}
void sort(Seqlist *list) //冒泡排序,由小到大
{
for (int i = 0; i < list->size - 1; i++)
{ //排序的趟数(例如5个数据需要比较4趟)
for (int j = 0; j < list->size - 1 - i; j++)
{ //每一趟比较中的比较次数(例如5个数据在第0趟需要比较4次)
if (list->base[j] > list->base[j + 1])
{
EType temp = list->base[j];
list->base[j] = list->base[j + 1];
list->base[j + 1] = temp;
}
}
}
}
void reverse(Seqlist *list) //逆置顺序表
{
if (list->size == 0 || list->size == 1) return;
int low = 0, high = list->size - 1;
while (low < high)
{
EType temp = list->base[low];
list->base[low] = list->base[high];
list->base[high] = temp;
low++;
high--;
}
}
void clear(Seqlist *list) //清除顺序表元素
{
list->size = 0;
}
void destroy(Seqlist *list) //销毁顺序表
{
free(list->base);
list->base = NULL;
list->capacity = 0;
list->size = 0;
}
void merge(Seqlist *list, Seqlist *alist, Seqlist *blist) //合并两个顺序表
{
list->capacity = alist->size + blist->size;
list->base = (EType*)malloc(sizeof(EType)*list->capacity);
assert(list->base != NULL);
int ia = 0, ib = 0, ic = 0;
while (ia < alist->size&&ib < blist->size)
{
if (alist->base[ia] < blist->base[ib])
list->base[ic++] = alist->base[ia++];
else
list->base[ic++] = blist->base[ib++];
}
while (ia < alist->size)
list->base[ic++] = alist->base[ia++];
while (ib < blist->size)
list->base[ic++] = blist->base[ib++];
list->size = alist->size + blist->size;
showlist(list);
}
主函数"main.cpp"
#include"seqlist.cpp"
int main()
{
Seqlist list;
InitSeqlist(&list);
EType num;
int pos;
int chose = 1;
while (chose)
{
show();
scanf("%d", &chose);
if (chose == 0) break;
switch (chose)
{
case 1: //尾插
printf("请输入要插入的数据(-1结束):>");
while (scanf("%d", &num), num != -1) //先输入item的值,只要item不等于-1就接着循环
pushback(&list, num);
break;
case 2: //头插
printf("请输入要插入的数据(-1结束):>");
while (scanf("%d", &num), num != -1)
pushfront(&list, num);
break;
case 3: //打印顺序表
showlist(&list);
break;
case 4: //尾删
popback(&list);
break;
case 5: //头删
popfront(&list);
break;
case 6: //在顺序表选定下标位置插入数据
printf("请输入要插入的位置:>");
scanf("%d", &pos);
printf("请输入要插入的数据:>");
scanf("%d", &num);
insertpos(&list, pos, num);
break;
case 7: //查找顺序表中元素key的下标
printf("请输入要查找的数据:>");
scanf("%d", &num);
pos = find(&list, num);
if (pos == -1)
printf("查找的数据元素不在顺序表中!\n");
else
printf("查找的数据元素在顺序表中的下标位置为%d\n", pos);
break;
case 8: //求顺序表长度
printf("顺序表的长度为%d\n", length(&list));
break;
case 9: //删除顺序表中选定下标位置元素
printf("请输入要删除数据在顺序表中的下标位置:>");
scanf("%d", &pos);
deletepos(&list, pos);
break;
case 10: //删除顺序表中值为key的元素
printf("请输入要删除数据的值:>");
scanf("%d", &num);
deleteval(&list, num);
break;
case 11: //冒泡排序
sort(&list); break;
case 12: //逆置顺序表
reverse(&list); break;
case 13: //清除顺序表
clear(&list); break;
case 14: //合并两个顺序列表
Seqlist alist, blist; //先初始化两个顺序表
EType item1, item2; //也可以递上面定义的链表,但是仍需在定义一个链表
InitSeqlist(&alist);
InitSeqlist(&blist);
printf("请输入顺序表1中的元素值(-1结束):>");
while (scanf("%d", &item1), item1 != -1) //给两个顺序表添加元素
pushback(&alist, item1); //尾插
printf("请输入顺序表2中的元素值(-1结束):>");
while (scanf("%d", &item2), item2 != -1)
pushback(&blist, item2); //尾插
merge(&list, &alist, &blist); //合并函数
destroy(&alist); //合并后销毁原顺序表
destroy(&blist);
break;
default: //输出其他违规
printf("输入的选择错误!请重新输入!\n");
break;
}
}
destroy(&list); //退出时销毁
system("pause");
return 0;
}