其实前面文章的动态通讯录本质其实也是动态顺序表
该动态链表的主要功能实现如下(完整代码在最后):
1.初始化化顺序表
void SeqListInit(SL* ps)
{
ps->a = NULL;
ps->size = 0;
ps->capacity = 0;
}
这里使用typedf重新定义了类型(int) 后续如果需要插入其他类型时,只需改动int即可,结构体表里顺序表中包含三个元素:1.数据a。 2.统计有效数据个数的size。 3.顺序表的容量capacity。
typedef int SQDataType;
typedef struct SeqList
{
SQDataType* a;
int size;//有效数据的个数
int capacity;//顺序表的容量
}SL;
2.头插法
每次插入数据前需要先检查容量,所以定义一个检查容量的函数Check_Capacity,满了就进行增容
void Check_Capacity(SL* ps)
{
if (ps->size == ps->capacity)
{
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
SQDataType* pf = (SQDataType*)realloc(ps->a,sizeof(SQDataType) * newcapacity);
if (pf == NULL)
{
perror("");
return;
}
else
{
ps->a = pf;
}
ps->capacity = newcapacity;
}
}
头插法功能实现思路:从最后一个元素开始,依次向后移动,直到第一个结点值也被移动后,直接将x赋值给a[0]即可。
void SeqListPushFront(SL* ps, SQDataType x)
{
Check_Capacity(ps);
int end = ps->size - 1;
while (end>=0)
{
ps->a[end + 1] = ps->a[end];
end--;
}
ps->a[0] = x;
ps->size++;
}
3.尾插法:先判断容量,再进行插入,直接插入到size位置即可
void SeqListPushBack(SL* ps, SQDataType x)
{
Check_Capacity(ps);
ps->a[ps->size] = x;
ps->size++;
}
4.头删数据:从第二个结点开始,依次向前覆盖,最后size-1即可。
void SeqListPopFront(SL* ps)
{
assert(ps->size > 0);
int start = 0;
while (start <ps->size)
{
ps->a[start] = ps->a[start + 1];
start++;
}
ps->size--;
}
5.尾删数据:直接将size--即可。
void SeqListPopBack(SL* ps)
{
assert(ps->size > 0);
ps->size--;
}
6.查找数据:对顺序表进行遍历,如果找到数据就返回其下标,如果没找到就返回-1
int SeqListSearch(SL* ps, SQDataType x)
{
int i = 0;
for (i = 0; i<ps->size; i++)
{
if (ps->a[i] == x)
{
return i;
}
}
return -1;
}
7.随机插入:一般与查找数据功能连用,如果查找的数据存在,且返回的坐标用pos接收,直接将pos后面的数据从后向前依次向后移动一位,然后将要插入的数据直接保存再pos位置即可。
void SeqListInsert(SL* ps, int pos, SQDataType x)
{
Check_Capacity(ps);
assert(pos < ps->size);
int end = ps->size - 1;
while (end >= pos)
{
ps->a[end + 1] = ps->a[end];
end--;
}
ps->a[pos] = x;
ps->size++;
}
8.随机删除:与查找数据功能连用,用pos接收查找到的数据的坐标,然后从pos后面的第一个结点开始依次向前覆盖即可。
void SeqListErase(SL* ps, int pos)
{
assert(pos < ps->size);
while (pos<ps->size)
{
ps->a[pos] = ps->a[pos + 1];
pos++;
}
ps->size--;
}
9.修改数据:查找数据后用pos接收返回坐标,直接将要修改的数据赋值给pos即可(覆盖pos原来的数据)
void SeqListModify(SL* ps,int pos, SQDataType x)
{
assert(pos<ps->size);
ps->a[pos] = x;
}
10.打印数据:依次遍历打印顺序表
void SeqListPrint(SL* ps)
{
int i = 0;
for (i = 0; i < ps->size; i++)
{
printf("%d ", ps->a[i]);
}
printf("\n");
}
11.销毁顺序表
void DistroySeqList(SL* ps)
{
free(ps->a);
ps->a = NULL;
}
注:assert的使用以及每次size的变化需要注意
补充一下#pragma once 、#if 、#ifdef 、#ifndef
1.#pragma once 防止被重定义 等价于
2.#ifndef
中间是定义
#endif
3.#if 常量表达式
语句
#endif 如果#if后面的常量表达式为真,则执行下列语句,如果为加不执行
4.#ifdef +宏定义
语句
#endif 如果#ifdef后面定义过就执行下面的语句,没定义过就不执行
其实用随机插入以及随机删除就可以实现头插尾插,头删尾删等功能。比如头插时:
void SeqListPushFront(SL*ps,SQLTDatatype x)
{
SeqListInsert(ps,a[0],x);
}
UU们有不会的地方可以私信或者评论,1天内会回复嗷~
各位看官老爷们~如有帮助可以留下你的赞嘛~
头文件:SeqList
#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
typedef int SQDataType;
typedef struct SeqList
{
SQDataType* a;
int size;//有效数据的个数
int capacity;//顺序表的容量
}SL;
//顺序表的初始化 打印 销毁
void SeqListInit(SL* ps);
void SeqListPrint(SL* ps);
void DistroySeqList(SL* ps);
//顺序表的增删改查等功能
//尾插 头插 尾删 头删 随机插入 随即删除 查找 删除
void SeqListPushBack(SL* ps,SQDataType x);
void SeqListPushFront(SL* ps, SQDataType x);
void SeqListPopBack(SL* ps);
void SeqListPopFront(SL* ps);
void SeqListInsert(SL* ps,int pos, SQDataType x);
void SeqListErase(SL* ps,int pos);
int SeqListSearch(SL* ps, SQDataType x);
void SeqListModify(SL* ps, int pos, SQDataType x);
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#pragma once
typedef int SQDataType;
typedef struct SeqList
{
SQDataType* a;
int size;//有效数据的个数
int capacity;//顺序表的容量
}SL;
//顺序表的初始化 打印 销毁
void SeqListInit(SL* ps);
void SeqListPrint(SL* ps);
void DistroySeqList(SL* ps);
//顺序表的增删改查等功能
//尾插 头插 尾删 头删 随机插入 随即删除 查找 删除
void SeqListPushBack(SL* ps,SQDataType x);
void SeqListPushFront(SL* ps, SQDataType x);
void SeqListPopBack(SL* ps);
void SeqListPopFront(SL* ps);
void SeqListInsert(SL* ps,int pos, SQDataType x);
void SeqListErase(SL* ps,int pos);
int SeqListSearch(SL* ps, SQDataType x);
void SeqListModify(SL* ps, int pos, SQDataType x);
源文件SeqList.c(函数实现)
#include"SeqList.h"
//初始化顺序表
void SeqListInit(SL* ps)
{
ps->a = NULL;
ps->size = 0;
ps->capacity = 0;
}
//打印顺序表
void SeqListPrint(SL* ps)
{
int i = 0;
for (i = 0; i < ps->size; i++)
{
printf("%d ", ps->a[i]);
}
printf("\n");
}
//销毁顺序表
void DistroySeqList(SL* ps)
{
free(ps->a);
ps->a = NULL;
}
//增容
void Check_Capacity(SL* ps)
{
if (ps->size == ps->capacity)
{
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
SQDataType* pf = (SQDataType*)realloc(ps->a,sizeof(SQDataType) * newcapacity);
if (pf == NULL)
{
perror("");
return;
}
else
{
ps->a = pf;
}
ps->capacity = newcapacity;
}
}
//尾插法
void SeqListPushBack(SL* ps, SQDataType x)
{
Check_Capacity(ps);
ps->a[ps->size] = x;
ps->size++;
}
//头插法
void SeqListPushFront(SL* ps, SQDataType x)
{
Check_Capacity(ps);
int end = ps->size - 1;
while (end>=0)
{
ps->a[end + 1] = ps->a[end];
end--;
}
ps->a[0] = x;
ps->size++;
}
//尾删
void SeqListPopBack(SL* ps)
{
assert(ps->size > 0);
ps->size--;
}
//头删
void SeqListPopFront(SL* ps)
{
assert(ps->size > 0);
int start = 0;
while (start <ps->size)
{
ps->a[start] = ps->a[start + 1];
start++;
}
ps->size--;
}
//随机插入
void SeqListInsert(SL* ps, int pos, SQDataType x)
{
Check_Capacity(ps);
assert(pos < ps->size);
int end = ps->size - 1;
while (end >= pos)
{
ps->a[end + 1] = ps->a[end];
end--;
}
ps->a[pos] = x;
ps->size++;
}
//随机删除
void SeqListErase(SL* ps, int pos)
{
assert(pos < ps->size);
while (pos<ps->size)
{
ps->a[pos] = ps->a[pos + 1];
pos++;
}
ps->size--;
}
//查找
int SeqListSearch(SL* ps, SQDataType x)
{
int i = 0;
for (i = 0; i<ps->size; i++)
{
if (ps->a[i] == x)
{
return i;
}
}
return -1;
}
//修改
void SeqListModify(SL* ps,int pos, SQDataType x)
{
assert(pos<ps->size);
ps->a[pos] = x;
}
源文件text.c(功能测试)
#include"SeqList.h"
void menu()
{
printf("*************************************\n");
printf("**1.尾插数据 2.头插数据 \n");
printf("**3.删除尾数据 4.删除首数据\n");
printf("**5.随机插入数据 6.随机删除数据\n");
printf("**7.查找数据 8.修改数据**\n");
printf("**9.打印数据 0.退出程序\n");
printf("*************************************\n");
printf("请输入你的选择:>\n");
}
int main()
{
SL s;
int x = 0;
int input = 0;
int pos = 0;
SeqListInit(&s);
do
{
menu();
scanf("%d", &input);
switch (input)
{
case 1:
printf("请输入你要插入的数据,以-1结束\n");
do
{
scanf("%d", &x);
if (x != -1)
{
SeqListPushBack(&s, x);
}
} while (x != -1);
break;
case 2:
printf("请输入你要插入的数据,以-1结束\n");
do
{
scanf("%d", &x);
if (x != -1)
{
SeqListPushFront(&s, x);
}
} while (x != -1);
break;
case 3:
SeqListPopBack(&s);
break;
case 4:
SeqListPopFront(&s);
break;
case 5:
printf("请输入你要插入的数据\n");
do
{
scanf("%d", &x);
if (x != -1)
{
printf("请输入你要插入的下标,以-1结束:\n");
scanf("%d", &pos);
SeqListInsert(&s,pos,x);
}
}while (x != -1);
break;
case 6:
printf("请输入你要删除的下标,以-1结束:\n");
do
{
scanf("%d", &x);
if (x != -1)
{
SeqListErase(&s, x);
}
} while (x != -1);
break;
case 7:
printf("请输入你要查找的数据,以-1结束:\n");
do
{
scanf("%d", &x);
if (x != -1)
{
int ret=SeqListSearch(&s, x);
if (ret == -1)
{
printf("该数字不存在\n");
}
else
{
printf("该数字存在,且下标为:%d", ret);
}
}
} while (x != -1);
break;
case 8:
printf("请输入你要修改的数据\n");
do
{
scanf("%d", &x);
if (x != -1)
{
printf("请输入你要修改的下标,以-1结束:\n");
scanf("%d", &pos);
SeqListModify(&s, pos, x);
}
} while (x != -1);
break;
case 9:
SeqListPrint(&s);
break;
case 0:
printf("退出程序!\n");
break;
default:
printf("输入错误,请重新输入!\n");
break;
}
} while (input);
DistroySeqList(&s);
return 0;
}