前言:学习数据结构的框架:
一、线性表
线性表是最基本、最简单、也是最常用的一种数据结构。
线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(注意,这句话只适用大部分线性表,而不是全部。比如,循环链表逻辑层次上也是一种线性表(存储层次上属于链式存储),但是把最后一个数据元素的尾指针指向了首位结点)。
我们说“线性”和“非线性”,只在逻辑层次上讨论,而不考虑存储层次,所以双向链表和循环链表依旧是线性表。
在数据结构逻辑层次上细分,线性表可分为一般线性表和受限线性表。
一般线性表也就是我们通常所说的“线性表”,可以自由的删除或添加结点。
受限线性表主要包括栈和队列,受限表示对结点的操作受限制。
线性表的逻辑结构简单,便于实现和操作。
因此,线性表这种数据结构在实际应用中是广泛采用的一种数据结构。
二、顺序表
顺序表是在计算机内存中以数组的形式保存的线性表,是指用一组地址连续的存储单元依次存储数据元素的线性结构。线性表采用顺序存储的方式存储就称之为顺序表。顺序表是将表中的结点依次存放在计算机内存中一组地址连续的存储单元中。
三、静态顺序表:
是指顺序表的储存是一个静态数组;储存数据有限;
四、代码实现:
主要实现功能:
void InitSeq(pSeqList pSeq);//初始化顺序表
void PrintfSeq(pSeqList pSeq);//打印顺序表内容
void PushBack(pSeqList pSeq,DataType x);//尾插
void PopBack(pSeqList pSeq);//尾删
void PushFront(pSeqList pSeq,DataType x);//头插
void PopFront(pSeqList pSeq);//头删
void Insert(pSeqList pSeq,int pos,DataType x);//在顺序表某位置插入某个特定元素
void Remove(pSeqList pSeq,DataType x);//删除在顺序表第一次出现的某个特定元素
void RemoveAll(pSeqList pSeq,DataType x);//删除顺序表中某个所有出现的元素
void Sort(pSeqList pSeq);//排序--升序
void BinarySearch(pSeqList pSeq,DataType x);//二分查找
SeqList.h
//静态顺序表的------底层实现原理(静态数组)
#include<stdio.h>
#include<assert.h>
#include<memory.h>
#include <stdlib.h>
typedef int DataType;//顺序表元素类型
#define MAX 100//顺序表的数组的大小,即就是储存元素的多少
typedef struct SeqList
{
DataType arr[MAX];
int sz;//顺序表当前储存元素的个数
}Seqlist,*pSeqList;
//函数声明
void InitSeq(pSeqList pSeq);//初始化顺序表---✔
void PrintfSeq(pSeqList pSeq);//打印顺序表内容---✔
void PushBack(pSeqList pSeq,DataType x);//尾插---✔
void PopBack(pSeqList pSeq);//尾删---✔
void PushFront(pSeqList pSeq,DataType x);//头插---✔
void PopFront(pSeqList pSeq);//头删---✔
void Insert(pSeqList pSeq,int pos,DataType x);//在顺序表某位置插入某个特定元素---✔
void Remove(pSeqList pSeq,DataType x);//删除在顺序表第一次出现的某个特定元素---✔
void RemoveAll(pSeqList pSeq,DataType x);//删除顺序表中某个所有出现的元素---✔
void Sort(pSeqList pSeq);//排序--升序---✔
void BinarySearch(pSeqList pSeq,DataType x);//二分查找---✔
test.c
#include"SeqList.h"
void InitSeq(pSeqList pSeq)//初始化顺序表
{
assert(pSeq);
memset( pSeq->arr,0,sizeof(DataType)*MAX);
pSeq->sz=0;
}
void PrintfSeq(pSeqList pSeq)//打印顺序表内容
{
int i=0;
assert(pSeq);
if (pSeq->sz==0)
{
printf("顺序表没有元素");
exit(EXIT_FAILURE);
}
for (i=0;i<pSeq->sz;++i)
{
printf("%d ",pSeq->arr[i]);
}
printf("\n");
}
void PushBack(pSeqList pSeq,DataType x)//尾插
{
assert(pSeq);
if (pSeq->sz==MAX)
{
printf("顺序表已满\n");
exit(EXIT_FAILURE);
}
pSeq->arr[pSeq->sz]=x;
++pSeq->sz;
}
void PopBack(pSeqList pSeq)//尾删
{
assert(pSeq);
if (pSeq->sz==0)
{
printf("顺序表没有元素;不可删除\n");
exit(EXIT_FAILURE);
}
--pSeq->sz;
}
void PushFront(pSeqList pSeq,DataType x)//头插
{
int i=0;
assert(pSeq);
if (pSeq->sz==MAX)
{
printf("顺序表已满\n");
exit(EXIT_FAILURE);
}
for ( i=pSeq->sz;i>0;--i)
{
pSeq->arr[i]=pSeq->arr[i-1];
}
pSeq->arr[0]=x;
++pSeq->sz;
}
void PopFront(pSeqList pSeq)//头删
{
int i=0;
assert(pSeq);
if (pSeq->sz==0)
{
printf("顺序表没有元素;不可删除\n");
exit(EXIT_FAILURE);
}
for (i=0;i<pSeq->sz-1;++i)
{
pSeq->arr[i]=pSeq->arr[i+1];
}
--pSeq->sz;
}
void Insert(pSeqList pSeq,int pos,DataType x)//在顺序表某位置插入某个特定元素
{
int i=0;
assert(pSeq);
if (pSeq->sz==MAX)
{
printf("顺序表已满\n");
exit(EXIT_FAILURE);
}
if (pos>=MAX)
{
printf("插入位置不合适\n");
exit(EXIT_FAILURE);
}
for (i=pSeq->sz;i>pos;--i)
{
pSeq->arr[i]=pSeq->arr[i-1];
}
pSeq->arr[pos]=x;
++pSeq->sz;
}
void Remove(pSeqList pSeq,DataType x)//删除在顺序表第一次出现的某个特定元素
{
int i=0;
int j=0;
assert(pSeq);
if (pSeq->sz==0)
{
printf("顺序表为空;不可删除\n");
exit(EXIT_FAILURE);
}
for (i=0;i < (pSeq->sz);++i)
{
if (pSeq->arr[i]==x)
{
for (j=i;j<pSeq->sz-1;++j)
{
pSeq->arr[j]=pSeq->arr[j+1];
}
--pSeq->sz;
break;
}
}
return;
}
void RemoveAll(pSeqList pSeq,DataType x)//删除顺序表中某个所有出现的元素
{
int i=0;
int j=0;
assert(pSeq);
if (pSeq->sz==0)
{
printf("顺序表没有元素;不可删除\n");
exit(EXIT_FAILURE);
}
for (i=0;i<pSeq->sz;++i)
{
if (pSeq->arr[i]==x)
{
for (j=i;j<pSeq->sz-1;++j)
{
pSeq->arr[j]=pSeq->arr[j+1];
}
--pSeq->sz;//记得--元素个数;要不然上增循环会越界;
/*删除元素以后(后面覆盖前面),记得将下标回到前一位置;
再次进入循环,i会走到刚才的位置;现在是新的元素;这样可以
避免漏检查元素,可以有效删除出相连相同的元素;*/
i=i-1;
}
}
return ;
}
void Sort(pSeqList pSeq)//排序--升序
{
int i=0;
int j=0;
int mark=0;
DataType tmp=0;
assert(pSeq);
if (pSeq->sz==0)
{
printf("顺序表没有元素,不用排序\n");
exit(EXIT_FAILURE);
}
for (j=0;j<pSeq->sz-1;++j)//趟数
{
for (i=0;i<pSeq->sz-1-j;++i)//没趟比较次数
{
if (pSeq->arr[i]>pSeq->arr[i+1])//交换
{
mark=1;
tmp=pSeq->arr[i];
pSeq->arr[i]=pSeq->arr[i+1];
pSeq->arr[i+1]=tmp;
}
}
if (mark==0)
break;
}
}
void BinarySearch(pSeqList pSeq,DataType x)//二分查找
{
int left=0;
int right=pSeq->sz-1;
int mid=0;
assert(pSeq);
if (pSeq->sz==0)
{
printf("顺序表没有元素,不用排序\n");
exit(EXIT_FAILURE);
}
Sort(pSeq);
while(left<=right)
{
mid=(left+right)/2;
if (x>pSeq->arr[mid])
{
left=mid+1;
}
if (x<pSeq->arr[mid])
{
right=mid-1;
}
if (x==pSeq->arr[mid])
{
printf("该元素存在,且在顺序表的第%d位置\n",mid);
return ;
}
}
printf("该元素不存在");
}
main.c
#include"SeqList.h"
void Test()
{
Seqlist s;//用结构体创建一个顺序表
InitSeq(&s);
PushBack(&s,1);
PushBack(&s,2);
PushBack(&s,3);
PushBack(&s,3);
PushBack(&s,3);
PushBack(&s,3);
PushBack(&s,4);
PushBack(&s,3);
PushBack(&s,5);
PushBack(&s,2);
PushBack(&s,3);
PushBack(&s,6);
printf("尾插:");
PrintfSeq(&s);
PushFront(&s,9);
PushFront(&s,8);
PushFront(&s,7);
printf("头插三个数:");
PrintfSeq(&s);
PopBack(&s);
printf("尾删一个数:");
PrintfSeq(&s);
PopFront(&s);
printf("头删一个数:");
PrintfSeq(&s);
Insert(&s,3,99);
printf("给顺序表第三个位置删插入99:");
PrintfSeq(&s);
Remove(&s,2);
printf("删除顺序表中第一个出现的2:");
PrintfSeq(&s);
RemoveAll(&s,3);
printf("删除顺序表中所有的3:");
PrintfSeq(&s);
Sort(&s);
printf("排序:");
PrintfSeq(&s);
printf("查找4:");
BinarySearch(&s,4);
}
int main()
{
Test();
return 0;
}
四、运行结果
接下来是动态顺序表的实现!