数据结构复习
1-1线性表
一.线性表的定义
线性表(List):零个或多个数据元素的有限序列。
它是一个序列,元素之间是有顺序的,第一个元素无前驱,最后一个元素无后继,其他每个元素都有且只有一个前驱和后继。
它是有限的。
线性表元素的个数 n (n≥0) 定义为线性表的长度,当 n=0 时,称为空表。
复杂的线性表中,一个数据元素可以由若干个数据项组成。
- 优点
1.无须为表示表中元素之间的逻辑关系而增加额外的存储空间。
2.可以快速地存取表中任一位置的元素。 - 缺点
1.插入和删除操作需要移动大量元素。
2.当线性表长度变化较大时,难以确定存储空间的容量。
3.造成存储空间的“碎片”。
#include <stdio.h>
#include <stdlib.h>
/*此处是顺序线性表数据结构定义*/
typedef int DataType;
struct seqList
{//有3个数据成员
int MAXNUM;//用于记录顺序线性表中能存放的最大元素个数的 整型 MAXNUM
int curNum;//用于存放顺序线性表中数据元素的个数 整型 curNum
DataType *element;//用于存放顺序线性表数据元素的连续空间的起始地址
};
typedef struct seqList *PseqList;
//第一关
PseqList createNullList_seq(int m)
{//此处填写代码,创建一个空的顺序线性表,能存放的最大元素个数为 m
//若m=0,则返回NULL
if(m==0) return NULL;
PseqList head = (PseqList)malloc(sizeof(struct seqList));
if(head == NULL) return NULL;
head->MAXNUM = m;
head->curNum = 0;
head->element = (DataType*)malloc(m*sizeof(DataType));
if(head->element == NULL)
{
free(head);
return NULL;
}
return head;
}
//第二关
int isFullList_seq(PseqList L)
{
//判断顺序线性表是否已满,若已满,返回值为1,否则返回值为0
if (L->curNum == L->MAXNUM)
{
return 1;
}
return 0;
}
int insertP_seq(PseqList L , int p ,int x)
{// 在线性表L中下标为p的位置插入数据元素x,若下标p非法或线性表已满无法插入数据,返回0;插入成功返回值为1
//如果线性表满了, 还需输"list is full"的提示
//如果插入位置非法,需输出提示"position is illegel"
if(isFullList_seq( L ))
{
printf("list is full");
return 0;
}
if(p > L->MAXNUM || p<0)
{
printf("position is illegel");
return 0;
}
int i;
for(i=L->curNum-1;i>=p;i--)
{
L->element[i+1]=L->element[i];
}
L->element[p]=x;
L->curNum++;
return 1;
}
int insertPre_seq(PseqList L , int p ,int x)
{
// 在线性表L中下标为p的位置的前面插入数据元素x,若下标p非法或线性表已满无法插入数据,返回0;插入成功返回值为1
//提示:直接调用insertP函数实现即可
insertP_seq(L,p-1,x);
}
int insertPost_seq(PseqList L , int p ,int x)
{
// 在线性表L中下标为p的位置的后面插入数据元素x,若下标p非法或线性表已满无法插入数据,返回0;插入成功返回值为1
//提示:直接调用insertP函数实现即可
insertP_seq(L,p+1,x);
}
void printList_seq(PseqList L)
{//逐个输出线性表的元素,相邻的两个数据元素之间以一个空格为分隔符隔开
for(int i=0;i<L->curNum;i++)
{
printf("%d ",L->element[i]);
}
}
//第三关
int destroyList_seq(PseqList L)
{
//返回值为销毁的线性表中现有数据元素的个数,若待销毁的线性表不存在,则返回0
if(L==NULL)
{
return 0;
}
int num=L->curNum;
L->curNum=0;
L->MAXNUM=0;
free(L->element);
free(L);
return num;
}
//第四关
int locate_seq(PseqList L,int x)
{//在顺序表L中查找给定值x首次出现的位置,若不存在给定值,则返回-1
for(int i=0;i<L->curNum;i++)
{
if(L->element[i] == x)
{
return i;
}
}
return -1;
}
DataType locatePos_seq(PseqList L,int pos)
{// 在顺序表L中查找指定位置pos处的数据元素,若位置非法,则返回第0个数据元素
if(pos<0||pos>=L->curNum)
{
return L->element[0];
}
return L->element[pos];
}
//第五关
int deletePos_seq(PseqList L,int pos)
{//在顺序表L中删除与下标pos处的数据元素,若pos非法,则返回-1;否则返回1
if(pos<0||pos>=L->curNum)
{
return -1;
}
for(int i=pos;i<L->curNum-1;i++)
{
L->element[i]=L->element[i+1];
}
L->curNum--;
return 1;
}
int delete_seq(PseqList L,int x)
{//在顺序表L中删除与参数x值相同的数据元素,返回删除数据元素的个数
//可以使用之前已完成的操作
int i,pos;
int num=L->curNum;
for(i=0;i<num;i++)
{
pos=locate_seq(L,x);
if(pos != -1)
{
deletePos_seq(L,pos);
}
else
{
return i;】
}
}
}
//第六关
void replace_seq(PseqList L,int x,int y)
{//将顺序表L中值为x的数据元素替换为y
for(int i=0;i<L->curNum;i++)
{
int pos=locate_seq(L,x);
if(pos == -1)
{
return ;
}
L->element[pos]=y;
}
}
void delDuplicate_seq(PseqList L)
{//移除线性表中的所有重复元素;不要使用额外的数组空间,必须在原地修改输入数组 并在使用 O(1) 额外空间的条件下完成
//使用常规删除即可,已修改测试用例
for(int i=0;i<L->curNum;i++)
{
int num=L->element[i],flag=0;
for(int j=i+1;j<L->curNum;j++)
{
flag=delete_seq(L,num);
}
if(flag>0)
{
delete_seq(L,num);
}
}
}
#include <stdio.h>
#include <stdlib.h>
/*此处是顺序线性表数据结构定义*/
typedef int DataType;
struct seqList
{//有3个数据成员
int MAXNUM;//用于记录顺序线性表中能存放的最大元素个数的 整型 MAXNUM
int curNum;//用于存放顺序线性表中数据元素的个数 整型 curNum
DataType *element;//用于存放顺序线性表数据元素的连续空间的起始地址
};
typedef struct seqList *PseqList;
/*创建空的顺序线性表,能存放的最大元素个数为 m*/
PseqList createNullList_seq(int m)
{ //若m=0,则返回NULL
PseqList plist = (struct seqList *)malloc(sizeof(struct seqList));
if(plist == NULL) return NULL; //分配空间失败
plist->MAXNUM = m ;
plist->curNum = 0;
plist->element = (DataType *)malloc(sizeof(DataType)*m);
if(plist->element == NULL)
{
free(plist);
return NULL;
}
return plist;
}
/*在线性表表尾插入数据元素,返回值0表示插入失败,返回值1表示在表尾插入成功*/
int insertP_tail(PseqList plist , int x)
{
if(plist->curNum == plist->MAXNUM) //若表满,则无法插入
{
printf("list if full !");
return 0;
}
plist->element[plist->curNum] = x ;
plist->curNum++;
return 1;
}
/*回收线性表占用的空间*/
int destroyList_seq(PseqList plist)
{
//返回值为销毁的线性表中现有数据元素的个数,若待销毁的线性表不存在,则返回0
if(plist == NULL) return 0;
int m = plist->curNum;
free(plist->element);
free(plist);
return m;
}
void printList_seq(PseqList plist)
{//逐个输出线性表的元素,相邻的两个数据元素之间以一个空格为分隔符隔开
for(int i=0;i<plist->curNum;i++)
printf("%d ",plist->element[i]);
}
//第一关:求顺序线性表中连续子表(最少有一个元素)的最大和并输出
int seqMaxSum(PseqList plist)
{
int sum[1005]={0};
for(int i=0;i<plist->curNum;i++)
{
if(i==0)
{
sum[i]=plist->element[i];
}
else
{
sum[i]=sum[i-1]+plist->element[i];
}
if(sum[i]<0)sum[i]=0;
}
int maxx=-9999999;
for(int i=0;i<plist->curNum;i++)
{
if(maxx<sum[i])maxx=sum[i];
}
return maxx;
}
//第二关:寻找线性表中没有出现的最小的正整数
int findMinNumber(PseqList plist)
{
//若线性表为空,则返回0
if(plist->curNum==0)return 0;
int f[105]={0};
for(int i=0;i<plist->curNum;i++)
{
if(plist->element[i]>0)f[plist->element[i]]=1;
}
for(int i=1;i<=100;i++)
{
if(f[i]==0)return i;
}
}
//第三关:找出给定目标值target在有序线性表中出现的起始位置和结束位置
void findPos(PseqList plist,int target, int *pos)
{
//起始位置放在pos[0], 结束位置放在pos[1]
int l=0,r=plist->curNum-1,mid;
//curNum表示这个链表一共有多少个数据,但是在设置有边界的时候我们一定要让他-1
//因为题目给的出是位置是0,因此右边界=curNum-1;
pos[0]=-1;//先定义初始位置为-1,因为位置没有-1
//找得到target,初始位置比不可能为-1,否则就返回-1 -1
while(l<=r)//二分查找
{
mid=(l+r)/2;
if(plist->element[mid]>target)//目标值可能在mid的右边
{
r=mid-1;
}
else if(plist->element[mid]==target)//找到目标值,继续往右边找(找初始点)
{
pos[0]=mid;
r=mid-1;
}
else l=mid+1;//目标可能在mid的左边
}
if(pos[0]==-1)//如果上面的二分找不到目标值,则说明链表里不存在目标值
{
pos[1]=-1;
return ;
}
//找目标值的终点
l=0,r=plist->curNum-1;
while(l<=r)
{
mid=(l+r)/2;
if(plist->element[mid]==target)//找到目标值,继续往左边找
{
pos[1]=mid;
l=mid+1;
}
else if(plist->element[mid]<target)//目标值可能在mid的左边
{
l=mid+1;
}
else r=mid-1;//目标值可能在mid的右边
}
}
#include <stdio.h>
#include <stdlib.h>
//第一关代码
struct node
{//此处填写代码,定义链表结点类型,包含一个存放整型数据的 data 成员,和一个指向下一个结点的next成员
int data;
struct node * next;
};
struct node *mycreateList()
{//此处填写代码,创建一个只有一个头结点的空链表,头节点的数据域赋值为0,并将表头结点的地址返回
struct node * p;
p=(struct node*) malloc(sizeof(struct node));
p->next=NULL;
p->data=0;
return p;
}
//第二关代码
void myinsertHead(struct node * head, int insData )
{
/*在此处完成任务,实现在head为表头d 链表的头插数据元素insData的功能*/
//begin
struct node * newHead=( struct node *) malloc(sizeof(struct node));
newHead->data=insData;
newHead->next=head->next;
head->next=newHead;
//end
}
void myinsertTail(struct node * head , int insData )
{
/*在此处完成任务,在head为表头的单链表表尾插入数据元素insData*/
struct node * p=head;
//begin
while(p->next!=NULL){
p=p->next;
}
struct node * newTail=( struct node *) malloc(sizeof(struct node));
newTail->data=insData;
newTail->next=NULL;
p->next=newTail;
//end
}
void myprintList(struct node *L)
{
/*在此处完成任务,输出head为表头链表中的数据,每输出一个数据换一行*/
//begin
struct node * p=L->next;
//begin
while(p->next!=NULL){
printf("%d\n",p->data);
p=p->next;
}
printf("%d\n",p->data);
//end
}
//第三关代码
void reverseList_link( struct node *L)
{
//请在此处填入代码,实现链表逆置功能
//begin
struct node * newHead=( struct node *) malloc(sizeof(struct node));
struct node *p=L->next;
while(p!=NULL){
myinsertHead(newHead,p->data);
p=p->next;
}
L->next=newHead->next;
//end
}
//第四关代码
int locateAndChange( struct node *L, int data)
{
//请在此处填入代码,在头结点为L的链表中查找 与data值相等的第一个结点,若能找到该结点,则将该结点的值与前驱结点的值交换
//若未找到与data值相等的结点,则返回值为-1,若找到的结点无前驱结点,则返回值为0,否则返回值为前驱结点的值
//begin
struct node *p=L->next;
if(p->data==data) return 0;
while(p!=NULL){
if(p->next!=NULL&&p->next->data==data){
int s;
s=p->data;
p->data=p->next->data;
p->next->data=s;
return s;
}
p=p->next;
}
return -1;
//end
}
//第五关代码
int destroyList(struct node *L)
{
//请在此处填写代码,实现将链表L的结点空间回收
//返回值为回收结点的个数,含头结点在内
int count=0;
struct node *p=L;
while(p!=NULL){
count++;
p=p->next;
}
free(L);
return count;
}
下面是我从网上找到的一篇数据结构总结,可能会对你有帮助
提取码:6666数据结构和算法5.0.pdf