顺序表和链式表

1.数据元素之间不是独立的,存在特定的关系,这些关系即结构。所以数据结构是指数据对象中数据元素之间的关系。

数据结构分为逻辑结构和物理结构。

逻辑结构分为:

集合结构:数据元素之间没有特别的关系,仅同属相同集合。

线性结构:数据元素之间是一对一的关系。

树形结构:数据元素之间存在一对多的层次关系。

图形结构:数据元素之间是多对多的关系。

物理结构分为:

顺序存储结构:将数据存储在地址连续的存储单元里。

链式存储结构:将数据存储在任意的存储单元里,通过保存地址的方式找到相关联的数据元素。

线性表的定义:

线性表(List)是零个或多个数据元素的集合。

线性表中的数据元素之间是有顺序的。

线性表中的数据元素个数是有限的。

线性表中的数据元素的类型必须相同。

性质:

a0为线性表的第一个元素只有一个后继。

an为线性表的最后一个元素,只有一个前驱。

除a0和an外的其他元素既有前驱又有后继。

线性表能够逐项访问和顺序存取。

2.顺序存储结构:线性表的顺序存储结构指的是用一段地址连续的存储单元依次存储线性表的数据元素。

(1)插入元素算法:

判断线性表是否合法

判断插入位置是否合法

把最后一个元素到插入位置的元素后移一个位置

将新元素插入

线性表长度加1

Status ListInsert(SqList *L,int i,ElemType e)

int k;
if (L->length==MAXSIZE)                                /* 顺序线性表已经满 */
return ERROR;

if (i<1 || i>L->length+1)                             /* 当i比第一位置小或者比最后一位置后一位置还要大时 */

return ERROR;

if (i<=L->length)                                     /* 若插入数据位置不在表尾 */
{
for(k=L->length-1;k>=i-1;k--)                       /* 将要插入位置之后的数据元素向后移动一位 */
L->data[k+1]=L->data[k];
}
L->data[i-1]=e;                                       /* 将新元素插入 */

L->length++;

return OK;

}

(2)删除元素算法: 

判断线性表是否合法

判断删除位置是否合法

将元素取出

将删除位置后的元素分别向前移动一个位置

线性表长度减1

Status ListDelete(SqList *L,int i,ElemType *e) 


    int k;   

    if (L->length==0)               /* 线性表为空 */

         return ERROR;    

    if (i<1 || i>L->length)         /* 删除位置不正确 */

          return ERROR;

        *e=L->data[i-1];    

    if (i<L->length)                /* 如果删除不是最后位置 */ 

    {           

       for(k=i;k<L->length;k++)        /* 将删除位置后继元素前移 */

  L->data[k-1]=L->data[k];    

     }   

 L->length--; 

 return OK;

}

3.链式存储结构:

为了表示每个元素与其直接后继元素之间的逻辑关系,每个元素除了存储本身的信息外,还需要存储指示其直接后继的信息。

链表的概念:

表头结点------链表中的第一个结点,包含指向第一个数据元素的指针以及链表自身的一些信息。

数据结点------链表中代表数据元素的结点,包含指向下一个数据元素的指针和数据元素的信息。

尾结点--------链表中的最后一个数据结点,其下一元素指针为空,表示无后继。

N个结点链接成一个链表,即为线性表(a1,a2,…an)的链式存储结构,因为此链表的每个结点中只包含一个指针域,所以叫单链表。

链表中第一个结点的存储位置叫做头指针;最后一个结点指针为空(NULL)。

可在单链表的第一个结点前附设一个结点,称为头结点。可以不存储任何信息。 

(1)单链表整表创建的算法思路:

声明一结点p和计数器变量i;

初始化一空链表L;

让L的头结点的指针指向NULL,即建立一个带头结点的单链表;

循环:

生成一新结点赋值给p;

随机生成一数字赋值给p的数据域p->data;

将p插入到头节点与新节点之间。

void CreateListHead(LinkList *L, int n) 
{
LinkList p;
int i;
srand(time(0));                         /* 初始化随机数种子 */
*L = (LinkList)malloc(sizeof(Node));
(*L)->next = NULL;                      /*  先建立一个带头结点的单链表 */

for (i=0; i<n; i++) 
{
p = (LinkList)malloc(sizeof(Node)); /*  生成新结点 */
p->data = rand()%100+1;             /*  随机生成100以内的数字 */
p->next = (*L)->next;    
(*L)->next = p; /*  插入到表头 */

}

}

上面那种叫做头插法,我们也可以通过尾插法来创建一个链表

void CreateListTail(LinkList *L, int n) 
{
LinkList p,r;
int i;
srand(time(0));                      /* 初始化随机数种子 */
*L = (LinkList)malloc(sizeof(Node));                 /* L为整个线性表 */
r=*L;                                /* r为指向尾部的结点 */
for (i=0; i<n; i++) 
{
p = (Node *)malloc(sizeof(Node));             /*  生成新结点 */
p->data = rand()%100+1;                     /*  随机生成100以内的数字 */
r->next=p;                        /* 将表尾终端结点的指针指向新结点 */
r = p;                            /* 将当前的新结点定义为表尾终端结点 */
}
r->next = NULL;                       /* 表示当前链表结束 */

}

(2)获取链表第i个数据的算法思路:

声明一个结点p指向链表第一个结点,初始化j从1开始;

当j<i时,就遍历链表,让p的指针向后移动,不断指向下一个结点,j累加1;

若到链表末尾p为空,则说明第i个元素不存在;

否则查找成功,返回结点p的数据;

Status GetElem(LinkList L,int i,ElemType *e)
{
int j;
LinkList p; /* 声明一结点p */
p = L->next;   /* 让p指向链表L的第一个结点 */

j = 1;        /*  j为计数器 */

while (p && j<i)             /* p不为空或者计数器j还没有等于i时,循环继续 */
{   
p = p->next;              /* 让p指向下一个结点 */
++j;

}

if ( !p || j>i ) 
return ERROR;         /*  第i个元素不存在 */
*e = p->data;                   /*  取第i个元素的数据 */
return OK;

}

(3)单链表第i个数据插入结点的算法思路:

声明一个结点p指向第一个结点,初始化j从1开始;

当j<i时,就遍历链表,让p的指针向后移动,不断指向下一个结点,j累加1;

若到链表末尾p为空,则说明第i个元素不存在;

否则查找成功,在系统中生成一个空结点s;

将数据元素e赋值给s->data;

单链表的插入标准语句:s->next = p->next; p->next = s;

返回成功。

Status ListInsert(LinkList *L,int i,ElemType e)

int j;
LinkList p,s;
p = *L;   
j = 1;
while (p && j < i)                                                     /* 寻找第i个结点 */
{
p = p->next;
++j;

if (!p || j > i) 

return ERROR;                                               /* 第i个元素不存在 */

s = (LinkList)malloc(sizeof(Node));                   /*  生成新结点(C语言标准函数) */
s->data = e;  
s->next = p->next;              /* 将p的后继结点赋值给s的后继  */

p->next = s;                        /* 将s赋值给p的后继 */

return OK;

}

(4)单链表第i个数据删除结点的算法思路:

声明一个结点p指向第一个结点,初始化j从1开始;

当j<i时,就遍历链表,让p的指针向后移动,不断指向下一个结点,j累加1;

若到链表末尾p为空,则说明第i个元素不存在;

否则查找成功,将欲删除的结点p->next赋值给q;

单链表的删除标准语句p->next = q->next;

将q结点中数据赋值给e,作为返回;

释放q结点;

返回成功;

Status ListDelete(LinkList *L,int i,ElemType *e) 

int j;
LinkList p,q;
p = *L;
j = 1;
while (p->next && j < i) /* 遍历寻找第i个元素 */
{
        p = p->next;
        ++j;
}
if (!(p->next) || j > i) 
   return ERROR;           /* 第i个元素不存在 */
q = p->next;
p->next = q->next; /* 将q的后继赋值给p的后继 */
*e = q->data;               /* 将q结点中的数据给e */

free(q);                         /* 让系统回收此结点,释放内存 */

     return OK;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值