第二章 线性表

@第二章 线性表

顺序表和链表的比较:
1、基于空间的比较
1)存储分配的方式:顺序表的存储空间是一次性分配的,链表的存储卡空间是多次分配的。
2)存储密度(存储密度=结点域值所占的存储量/结点结构所占的存储总量):
顺序表的存储密度=1,链表的存储密度<1(因为结点中有指针域)
2、基于时间的比较
1)存取方式:
顺序表可以随机存取,链表只能顺序存取
2)插入/删除时移动元素的个数:
顺序表平均需要移动近一半元素;链表不需要移动元素,只需要修改指针。

一、结构体定义

//顺序表的结构体定义
#define maxSize 100
typedef struct
{
  	int data[maxSize];
  	int length;
}Sqlist;
//或如下常用定义
 int A[maxSize];
 int n;  //n表示顺序表的长度

//单链表结点定义
typedef structure LNode
{
	int data;			//data中存放结点数据域
struct LNode *next;		//指向后继结点的指针
}LNode;					//定义单链表结点
//双链表结点定义
typedef struct DLNode
{
	int data;
	struct DLNode *prior;
	struct DLNode *next;
}DLNode;  //定义双链表的结点类型
LNode *A=(LNode *)malloc(sizeof(LNode));
//这里的A命名了两个东西:一个是结点,另一个是指向这个结点的指针;

二、顺序表的初始化、查找、插入及删除操作

//初始化顺序表
void initList(Sqlist &L)    //L本身要改变所以用引用型
{
    L.length=0;
}
//在顺序表中查找一个元素等于e的值
int findElem(Sqlist L,int e)
{
    int i;
    for(i=0;i<L.length;++i)
        if(e==L.data[i])
            return i;   //若找到返回下标
    return -1;          //若没找到,返回-1
}
//插入数据元素
int insertElem(Sqlist &L,int p,int e) //L本身要发生变化,所以用引用型
{
    int i;
    if(p<0||p>L.length||L.length==maxSize) //位置错误或者表长已经达到
        return 0;               //顺序表的最大允许值,此时插入不成功,返回0
    for(i=L.lenth-1;i>=p;--i)
        L.data[i+1]=L.data[i];  //从后往前,逐个讲元素往后移动一个位置
    L.data[p]=e;        //将e放在插入位置p上
    ++(L.lenth);    //表内元素多了一个,因此表长自增1
    return 1;       //插入成功,返回1
}
//删除操作
int deleteElem(Sqlist &L,int p,int &e) //要改变的变量用引用型
{
    int i;
    if(p<0||p>L.length-1)
        return 0;   //位置不对返回0,代表删除不成功
    e=L.data[p];  //将被删除元素赋给e
    for(i=p;i<L.lenth-1;++i) //从p位置开始,将后边的元素逐次前移一个位置
        L.data[i]=L.data[i+1];
    --(L.length);   //表长减1
    return 1;   //删除成功,返回1
}
//用e返回L中p位置上的元素
int getElem(Sqlist L,int p,int &e)  //要改变所以用引用型
{
    if(p<0||p>L.length-1)
        return 0;
    e=L.data[p];
    return i;
}

三、单链表的创建、归并、查找、删除操作。
单链表的的创建包括头插法和尾插法两种。

//尾插法建立链表C
void createListR(LNode *&C,int a[],int n)  //要改变的变量用引用型
{
    LNode *s ,*r;       //s用来指向新申请的结点,r始终指向C的终端结点
    int i;
    C=(LNode *)malloc(sizeof(LNode));   //申请C的头结点空间
    C->next=NULL;
    r=C;                        //r指向头结点,因为此时头结点就是终端结点
    for(i=0;i<n;++i)                //循环申请n个结点来接受数组a中的元素
    {
        s=(LNode *)malloc(sizeof(LNode));   //s指向新申请的结点
        s->data=a[i];           //用新申请的结点来接受a中的一个元素
        r->next=s;              //用r来接纳新结点
        r=r->next;              //r指向终端结点,以便接纳下一个到来的结点
    }
    r->next=NULL;        //数组a中的所以元素都已经转入链表C中,
   									 //C的终端结点的指针域置为NULL
}
//头插法建立链表C
void createListF(LNode *&C,int a[],int n)  
{
    LNode *s; 
    int i;
    C=(LNode *)malloc(sizeof(LNode));
    C->next=NULL;
    for(i=0;i<n;++i)
    {
        s=(LNode *)malloc(sizeof(LNode)); 
        s->data=a[i];  
        s->next=C->next;     //s所指新结点的指针域next指向C中的开始结点
        C->next=s;        //头指针的指针域指向s结点,使得s成为新的开始结点
    }
}
//A和B是两个带表头结点的单链表,其元素均递增有序,
//将A和B归并成一个元素非递减的链表C(采用尾插法)
void merge(LNode *A,LNode *B,LNode *C)
{
    LNode *p=A->next;       //p来追踪A的最小结点
    LNode *q=B->next;       //q来追踪B的最小结点
    LNode *r;               //r始终指向C的终端结点
    C=A;                    //用A的头结点来做C的头结点
    C->next=NULL;
    free(B);                //B的头结点已无用释放掉
    r=C;                    //r指向C,因为此时头结点也是终端结点
    while(p!=NULL && q!=NULL) 
     //当p与q都不空时,选取p与q所指结点中的较小者插入C的尾部
    { /*下面的语句中,r始终指向当前链表的终端结点,作为接纳新
    结点的一个媒介通过它新结点被链接入C并且重新指向新的终端
    结点,以便接受下一个新结点*/
        if(p->data<=q->data)
        {
            r->next=p;p=p->next;
            r=r->next;
        }
        else
        {
            r->next=q;q=q->next;
            r=r->next;
        }   
    }
    r->next=NULL;
/* 将还有剩余结点的链表链接在C的尾部 */
if(p!=NULL) r->next=p;
if(q!=NULL) r->next=q;
}
//采用头插法归并成递减的单链表算法
void merge(LNode *A,LNode *B,LNode *C)
{
    LNode *p=A->next;
    LNode *q=B->next;
    LNode *s;
    C=A;
    C->next=NULL;
    free(B);
    while(p!=NULL && q!=NULL)
    { //下面的if else 语句体现了链表的头插法
        if(p->data<=q->data)
        {
            s=p;p=p->next;
            s->next=C->next;
            C->next=s;
        }
        else
        {
            s=q;q=q->next;
            s->next=C->next;
            C->next=s;
        }   
    }
/*  必须将剩余元素逐个插入C的头部才能得到最终的递减序列 */
    while(p!=NULL)
    {
        s=p;
        p=p->next;
        s->next=C->next;
        C->next=s;
    }
    while(q!=NULL)
    {
        s=q;
        q=q->next;
        s->next=C->next;
        C->next=s;
    }
}
//查找并删除带头结点单链表中掉的一个值为x的结点
int findAndDelete(LNode *C,int x)
{
    LNode *p,*q;
    p=C;
    /*查找部分开始*/
    while(p->next!=NULL)
    {
        if(p->next->data=x)
            break;
        p=p->next;
    }
    /* 查找部分结束*/
    if(p->next=NULL)
        return 0;
    else
    {
        /*删除部分开始*/
        q=p->next;
        p->next=p->next->next;
        free(q);
        /*删除部分结束*/
        reuturn 1;
    }
} 

四、双链表建立、查找、插入、删除操作

//采用尾插法建立双链表
void createDlistR(DLNode *&L,int a[],int n)
{
    DLNode *s,*r;
    int i;
    L=(DLNode *)malloc(sizeof(DLNode));
    L->prior=NULL;
    L->next=NULL;
    r=L;  //r始终指向终端结点
    for(i=0;i<n;++i)
    {
        s=(DLNode *)malloc(sizeof(DLNode)); //创建新结点
        s->data=a[i];           
    /* 将s插入到L的尾部,并且r指向s,s->priror=r; */
    r->next=s;
    s->prior=r;
    r=s;
    }
    r->next=NULL;
}
//查找结点算法
DLNode* findNode(DLNode *C,int x)
{
    DLNode *p=C->next;
    while(p!=NULL)
    {
        if(p->data==x)
            break;
        p=p->next;
    }
    return p; //若找到,则p中内容是结点地址循环因break结束,       
    				//若未找到则p中内容是NULL
}
//插入结点操作
s->next=p->next;
s->prior=p;
p->next=s;
s->next->prior=s;
//删除结点操作
q=p->next;
p->next=q->next;
q->next->prior=p;
free(q);

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值