0
点赞
收藏
分享

微信扫一扫

ChatGPT新手指南:如何用AI写出专业学术论文

冶炼厂小练 04-10 09:00 阅读 1
数据结构

1. 线性表

顺序表 链表(单向链表 单向循环链表 双向链表 双向循环链表)
栈(顺序栈 链式栈) 队列(顺序队列 链式队列)
1)逻辑结构:线性结构
2)存储结构:顺序存储、链式存储
3)特点:
一对一,每个节点最多有一个前驱和一个后继
首尾节点比较特殊,首节点无前驱,尾节点无后继

1.1顺序表

特点:内存连续,数组
1)逻辑结构:线性结构
2)存储结构:顺序存储
3)操作:增删改查
相关操作:

#ifndef _SEQLIST_H_
#define _SEQLIST_H_
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<strings.h>
#define N 5
typedef struct 
{
	int data[N];
	int last;//last代表的是数组中最后一个有效元素的下标
}seqlist_t;
//1.创建一个空的顺序表
seqlist_t *CreateEpSeqlist();//返回的是申请空间的首地址
//2.向顺序表的指定位置插入数据
int InsertIntoSeqlist(seqlist_t *p, int post,int data);//post第几个位置,data插入的数据
//3.遍历顺序表sequence 顺序 list 表
void ShowSeqlist(seqlist_t *p);
//4.判断顺序表是否为满,满返回1 未满返回0
int IsFullSeqlist(seqlist_t *p);
//5.判断顺序表是否为空
int IsEpSeqlist(seqlist_t *p);
//6.删除顺序表中指定位置的数据post删除位置
int DeletePostSeqlist(seqlist_t *p, int post);
//7.清空顺序表
void ClearSeqList(seqlist_t *p);
//8.修改指定位置的数据
int ChangePostSeqList(seqlist_t *p,int post,int data);//post被修改的位置,data修改成的数据
//9.查找指定数据出现的位置
int SearchDataSeqList(seqlist_t *p,int data);//data代表被查找的数据
#endif

具体实现:

#include"seqlist.h"
//1.创建一个空的顺序表
seqlist_t *CreateEpSeqlist() //返回的是申请空间的首地址
{ //1.动态开辟一个结构体大小空间
   seqlist_t * p=(seqlist_t *)malloc(sizeof(seqlist_t));
    if(p == NULL)
    {
        perror("malloc error");
        return NULL;
    }
    //对last初始化,表示当前数据表为空
    p->last = -1;
    return p;
}
//2.判断顺序表是否为满,满返回1 未满返回0
int IsFullSeqlist(seqlist_t *p){
    return  p->last+1 == N;
}
//3.向顺序表的指定位置插入数据
int InsertIntoSeqlist(seqlist_t *p,int post,int data)
{
    //1.容错判断,如果不能插入则错误提示
    if(post>p->last+1 || post<0 || IsFullSeqlist(p))
    {
        perror("InsertIntoSeqlist err\n");
        return -1;
    }
    //向指定位置插入元素
    for(int i=p->last;i>=post;i--)
        p->data[i+1]=p->data[i];
    p->data[post]=data;
    //最后一个有效元素的下标+1
    p->last++;
    return 0;
}//post第几个位置,data插入的数据
//4.遍历顺序表sequence 顺序 list 表
void ShowSeqlist(seqlist_t *p)
{
for(int i=0;i<=p->last;i++)
{
    printf("%d ",p->data[i]);
}
printf("\n");
}
//5.判断顺序表是否为空
int IsEpSeqlist(seqlist_t *p)
{
    return p->last==-1;
}
//6.删除顺序表中指定位置的数据post删除位置
int DeletePostSeqlist(seqlist_t *p, int post)
{
    if(post>p->last || IsEpSeqlist(p) || post<0)
    {
        perror("delete error");
        return -1;
    }
    for(int i=post;i<p->last;i++)
    {
        p->data[i]=p->data[i+1];
    }
    //有效数据元素-1
    p->last--;
    return 0;
}
//7.清空顺序表
void ClearSeqList(seqlist_t *p)
{
    if( IsEpSeqlist(p))
    {
        perror("delete error");
    
    }
   p->last=-1;
    // for(int i=0;i<=p->last;i++)
    // {
    //     bzero(&(p->data[i]),1);
    // }
    
}
//8.修改指定位置的数据
int ChangePostSeqList(seqlist_t *p,int post,int data)
{
    if( IsEpSeqlist(p) || post>p->last || post<0)
    {
        perror("change error");
        return -1;
    }//判断位置是否存在
        p->data[post]=data;
        return 0;
}
//post被修改的位置,data修改成的数据
//9.查找指定数据出现的位置
int SearchDataSeqList(seqlist_t *p,int data)
{
   if( IsEpSeqlist(p))
    {
        perror("search error");
        return -1;
    
    }//判断列表是否为空
    int t=-1;
    for(int i=0;i<=p->last;i++)
    {
        if(p->data[i]==data) t=i;
    }
   return t;
}//data代表被查找的数据,只能查找数据的最后出现位置,且未查到返回-1

顺序表总结:
(1)顺序表在内存当中是连续存储的
(2)顺序表的长度是固定 #define N 5
(3)顺序表查找数据的时候方便的,插入和删除麻烦

1.2链表

单向链表 单向循环链表 双向 双向循环
解决了:长度固定,插入删除麻烦的问题
1)逻辑结构:线性结构
2)存储结构:链式存储结构
3)操作:增删改查

1.2.1单向链表

**相关操作**
#ifndef _LINKLIST_H_
#define _LINKLIST_H_
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef int datatype;
typedef struct node_t
{
	datatype data;//数据域
	struct node_t *next;//指针域,指向自身结构体的指针
}link_node_t,*link_list_t;

//1.创建一个空的单向链表(有头单向链表)
link_node_t *CreateEpLinkList();
//2.向单向链表的指定位置插入数据
//p保存链表的头指针 post 插入的位置 data插入的数据
int InsertIntoPostLinkList(link_node_t *p,int post, datatype data);
//3.遍历单向链表
void ShowLinkList(link_node_t *p);
//4.求单向链表长度的函数
int LengthLinkList(link_node_t *p);
//5.删除单向链表中指定位置的数据 post 代表的是删除的位置
int DeletePostLinkList(link_node_t *p, int post);
//6.判断单向链表是否为空 1代表空 0代表非空
int IsEpLinkList(link_node_t *p);
//7.修改指定位置的数据 post 被修改的位置 data修改成的数据
int ChangePostLinkList(link_node_t *p, int post, datatype data);
//8.查找指定数据出现的位置 data被查找的数据 //search 查找
int SearchDataLinkList(link_node_t *p, datatype data);
//9.删除单向链表中出现的指定数据,data代表将单向链表中出现的所有data数据删除
int DeleteDataLinkList(link_node_t *p, datatype data);
//10.转置链表
void ReverseLinkList(link_node_t *p);
//11.清空单向链表
void ClearLinkList(link_node_t *p);
#endif

具体实现

#include "linklist.h"
//1.创建一个空的单向链表(有头单向链表)
link_node_t *CreateEpLinkList()
{
    link_node_t *first=(link_node_t *)malloc(sizeof(link_node_t));
    if(first==NULL)
    {
        perror("malloc err\n");
        return NULL;
    }//开辟失败,错误返回
    first->next=NULL;
    first->data='\0';
    return first;
}
//2.求单向链表长度的函数
int LengthLinkList(link_node_t *p)
{
    int len=0;
    while(p->next!=NULL)
     {
        p=p->next;
        len++;
     }  
    return len;
}
//3.向单向链表的指定位置插入数据
//p保存链表的头指针 post 插入的位置 data插入的数据
int InsertIntoPostLinkList(link_node_t *p,int post, datatype data)
{
    if(post<0 || post>LengthLinkList(p))
     {
         perror("Insert err");
         return -1;
     }
      for(int i=0;i<post;i++)
        {
            p=p->next;
        }
    link_list_t pnew=(link_list_t)malloc(sizeof(link_node_t));
    if(pnew==NULL)
    {
        perror("pnew err");
        return -1;
    }//每次新开辟空间都要判断是否生成
    pnew->next=p->next;
    pnew->data=data;
    p->next=pnew;
    return 0;
    //新节点定义成指针类型,开辟新空间定义成全局变量存储防止函数内被释放
}
//4.判断单向链表是否为空 1代表空 0代表非空
int IsEpLinkList(link_node_t *p)
{
    return p->next==NULL;
}
//5.删除单向链表中指定位置的数据 post 代表的是删除的位置
int DeletePostLinkList(link_node_t *p, int post)
{
    if(post<0 || post >= LengthLinkList(p) || IsEpLinkList(p))
    {
        perror("delete error");
        return -1;
    }
    //头指针指向删除位置
    for(int i=0;i<post;i++)
        p=p->next;
    //定义一个pdel指向被删除节点
    link_list_t pdel=p->next;
    //跨过被删除节点
    p->next=pdel->next;
    //释放pdel
    free(pdel);
    pdel=NULL;
    return 0;
}
//6.遍历单向链表
void ShowLinkList(link_node_t *p)
{
   while(p->next!=NULL)
   {
       p=p->next;
       printf("%d ",p->data);
   }
   printf("\n");
}
//7.修改指定位置的数据 post 被修改的位置 data修改成的数据
int ChangePostLinkList(link_node_t *p, int post, datatype data)
{   //容错判断
    if(IsEpLinkList(p) || post<0 || post>=LengthLinkList(p))
    {
        perror("Change error");
        return -1;
    }
    while(post--)p=p->next;
    p->next->data=data;
    return 0;
}
//8.查找指定数据出现的位置 data被查找的数据 //search 查找
int SearchDataLinkList(link_node_t *p, datatype data)
{
    if(IsEpLinkList(p))
    {
        perror("Search error");
        return -1;
    }
    int i=-1,t=-1;
    while(p->next!=NULL)
    {
        p=p->next;i++;
        if(p->data==data)
           { printf("%d ",i);t++;}
    }
    if(t==-1)
    printf("Not Search");
    return 0;
}
//9.删除单向链表中出现的指定数据,data代表将单向链表中出现的所有data数据删除
int DeleteDataLinkList(link_node_t *p, datatype data)
{
    link_list_t pdel;
    if(IsEpLinkList(p))
    {
        perror("Delete error");
        return -1;
    }
   
    while(p->next!=NULL)
    {   
        if(p->next->data==data)
        {
            pdel=p->next;//指向被删除节点
            p->next=pdel->next;//跨过被删除节点
            free(pdel);//释放被删除节点
            pdel=NULL;
        }
        else
        p=p->next;
    }
    return 0;
}
//10.转置链表
void ReverseLinkList(link_node_t *p)
{
    // if(IsEpLinkList(p))
    // {
    //     perror("Reverse error");
    // }
   link_list_t q=p;
   link_list_t t;
    q=q->next;
    p->next=NULL;//将头节点摘下来注意q=q->next 要定义在p之前,否则q也指向null
   while(q!=NULL)
   {   
        t=q;//每次循环让t到q的位置,即新节点位置
        q=q->next;//q再向后走一个,到下一个新节点
        t->next=p->next;//新节点指向上一掉落节点
        p->next=t;//头节点指向当前掉落节点
   }
    
}
//11.清空单向链表(只释放数据部分,头指针不释放)
void ClearLinkList(link_node_t *p)
{
    link_list_t pdel=NULL;
    while(p->next!=NULL)
{
    pdel=p->next;//指向被删除节点
    p->next=pdel->next;//p跨过被删除节点
    free(pdel);//释放被删除节点
    pdel=NULL;
}
}

单向循环链表
实现约瑟夫环问题

总结:
顺序表和链表的区别?
(1)顺序表在内存当中连续存储的(数组),但是链表在内存当中是不连续存储的,通过指针将数据链接在一起
(2)顺序表的长度是固定的,但是链表长度不固定
(3) 顺序表查找方便,但是插入和删除麻烦,链表,插入和删除方便,查找麻烦

1.2.1双向链表

#ifndef _DOUBLELIST_H_
#define _DOUBLELIST_H_
#include <stdio.h>
#include <stdlib.h>
typedef int datatype;
typedef struct node_t
{
	datatype data;//数据域 
	struct node_t *next;//指向下一个节点的指针 next 下一个
	struct node_t *prior;//指向前一个节点的指针 prior 前一个
}link_node_t,*link_list_t;

//将双向链表的头指针和尾指针封装到一个结构体里 
//思想上有点像学的链式队列
typedef struct doublelinklist
{
	link_list_t head; //指向双向链表的头指针
	link_list_t tail; //指向双向链表的尾指针
	int len;
}double_node_t,*double_list_t;
//1.创建一个空的双向链表
double_list_t createEmptyDoubleLinkList();
//2.向双向链表的指定位置插入数据 post位置, data数据
int insertIntoDoubleLinkList(double_list_t p, int post, datatype data);
//3.遍历双向链表
void showDoubleLinkList(double_list_t p);
//4.删除双向链表指定位置的数据
int deletePostDoubleLinkList(double_list_t p, int post);
//5.判断双向链表是否为空
int isEmptyDoubleLinkList(double_list_t p);
//6.求双向链表的长度
int lengthDoubleLinkList(double_list_t p);
//7.查找指定数据出现的位置 data被查找的数据
int searchPostDoubleLinkList(double_list_t p,datatype data);
//8.修改指定位置的数据,post修改的位置 data被修改的数据
int changeDataDoubleLinkList(double_list_t p,int post, datatype data);
//9.删除双向链表中的指定数据 data代表删除所有出现的data数据
int deleteDataDoubleLinkList(double_list_t p, datatype data);

#endif

具体实现

#include "doublelist.h"

//1.创建一个空的双向链表
double_list_t createEmptyDoubleLinkList()
{
    double_list_t p=(double_list_t)malloc(sizeof(double_node_t));
    if(p==NULL)
    {
        perror("p err");
        return NULL;
    }
   p->tail=p->head=(link_list_t)malloc(sizeof(link_node_t));
    if(p->head==NULL)
    {
        perror("tail err");
        return NULL;
    }
    p->len=0;
    p->head->next=p->head->prior=NULL;
    return p;
}
//2.向双向链表的指定位置插入数据 post位置, data数据
int insertIntoDoubleLinkList(double_list_t p, int post, datatype data)
{
    //1.容错判断
    if(post<0 ||post>p->len)
    {
        perror("local error");
        return -1;
    }
    //2.开辟新节点
    link_list_t pnew=(link_list_t)malloc(sizeof(link_node_t));
    if(pnew==NULL)
    {
        perror("pnew err");
        return -1;
    }
    //初始化
     pnew->data=data;
    //插入位置判断 
    if(post==p->len)
    {//尾插 
        p->tail->next=pnew;
        pnew->prior=p->tail;
        pnew->next=NULL;
        p->tail=pnew;
    }
    else//中间插入
    {
        link_list_t temp;
        //判断插入位置在前在后
        if(post<p->len/2)
       {
           temp=p->head;
           for(int i=0;i<=post;i++)
            {
                temp=temp->next;
            }
       }      
     else
      {
         temp=p->tail;
         for(int i=0;i<p->len-post-1;i++)
         {
             temp=temp->prior;
         } 
      }
   //3.插入新节点
    temp->prior->next=pnew;
    pnew->prior=temp->prior;
    pnew->next=temp;
    temp->prior=pnew;
    }
    //长度+1
    p->len++;
    return 0;
}
//3.遍历双向链表
void showDoubleLinkList(double_list_t p)
{
    printf("顺序遍历:\n");
    link_list_t q=p->head;
    for(int i=0;i<p->len;i++)
    {
        q=q->next;
        printf("%d ",q->data);
    }
    printf("\n");
    printf("逆序遍历:\n");
    q=p->tail;
    for(int i=0;i<p->len;i++)
    {
        printf("%d ",q->data);
         q=q->prior;
    }
    printf("\n");
}
//4.判断双向链表是否为空
int isEmptyDoubleLinkList(double_list_t p)
{
    return p->head == p->tail;//p->len==0
}
//5.删除双向链表指定位置的数据
int deletePostDoubleLinkList(double_list_t p, int post)
{
    if(isEmptyDoubleLinkList(p) || post<0 || post >= p->len)
    {
        perror("del error");
        return -1;
    }
    link_list_t pdel;
    if(post == p->len-1)
    {
        pdel=p->tail;
        p->tail=pdel->prior;
        p->tail->next=NULL;
        free(pdel);
        pdel=NULL;
    }
    else
    {  
        if(post<p->len/2)
    {
        pdel=p->head;
        for(int i=0;i<=post;i++)
        {
            pdel=pdel->next;
        }
       
    }
     else 
    {
        pdel=p->tail;
        for(int i=0;i<p->len-post-1;i++)
        {
            pdel=pdel->prior;
        }        
    }
    pdel->prior->next=pdel->next;
    pdel->next->prior=pdel->prior;
    free(pdel);
    pdel=NULL;
    }
    p->len--;
    return 0;
}
//6.求双向链表的长度
int lengthDoubleLinkList(double_list_t p)
{
    return p->len;
}
//7.查找指定数据出现的位置 data被查找的数据
int searchPostDoubleLinkList(double_list_t p,datatype data)
{
    if(isEmptyDoubleLinkList(p))
    {
        perror("search list empty");
        return -1;
    }
    link_list_t temp=p->head;
    int i=-1;
    int flag=0;
    printf("%d位置在:",data);
    while(temp->next!=NULL)
    {
        temp=temp->next;
        i++;
        if(temp->data == data)
        {
            printf("%d ",i);flag++;
        }
    }
    if(flag==0)
    printf("no data");
    printf("\n");
    return 0;
}
//8.修改指定位置的数据,post修改的位置 data被修改的数据
int changeDataDoubleLinkList(double_list_t p,int post, datatype data)
{
    if(isEmptyDoubleLinkList(p))
    {
        perror("change list empty");
        return -1;
    }
    link_list_t temp;
    if(post<p->len/2)
    {
        temp=p->head;
        for(int i=0;i<=post;i++)
            temp=temp->next;
    }
    else
    {
        temp=p->tail;
        for(int i=0;i<p->len-post-1;i++)
            temp=temp->prior;
    }
    temp->data=data;
    return 0;
}
//9.删除双向链表中的指定数据 data代表删除所有出现的data数据
int deleteDataDoubleLinkList(double_list_t p, datatype data)
{
    link_list_t pdel=p->head->next;
    link_list_t temp=NULL;
    while(pdel!=NULL)
    {
        //尾删
        if(pdel->data == data)
        {
            if(pdel->next == NULL)
          { 
            p->tail=p->tail->prior;
            free(p->tail->next);
            p->tail->next=NULL;
          }
        else //中间删
          {
            temp=pdel;
            temp->prior->next=temp->next;
            temp->next->prior=temp->prior;
            pdel=temp->next;
            free(temp);
            temp=NULL;
          } 
          p->len--;
        }
       else pdel=pdel->next;
    }
    return 0;
}
举报

相关推荐

0 条评论