数据结构复习

数据结构复习

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱学习的【丿小菜鸡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值