大话数据结构——线性表

线性表(List):零或多个数据元素的有限序列。

线性表的抽象数据类型:

ADT 线性表 (List)
Data
Operation  
    void initList(*L);	//创建并初始化一个空线性表,如果成功返回true,修改表传指针   
    bool listEmpty(L);	//判断一个线性表是否为空,不修改表传值   
    void clearList(*L);	//清空一个线性表,成功返回true   
    bool getElem(L,i,*e);	//从某个位置取出元素并赋值给e(i的范围是[1,L.length]),修改e的值所以传递一个指针,成功返回true  
    int locateElem(L,e);	//查找线性表中是否有e,如果有返回它的位置(从1开始),否则返回0表示失败  
    bool listInsert(*L,i,e);	//插入一个元素e在第i个元素之前(i的取值范围是[1,L.length+1]) ,成功返回true   
    bool listDelete(*L,i,*e);	//删除在第i个位置上的元素(i的取值范围是[1,L.length]),删除的元素赋给e,成功返回true  
    int listLength(L);	//返回线性表的元素个数  
endADT

线性表的顺序存储结构:

用一段地址连续的存储单元依次存储线性表的数据元素。

#define MAXSIZE 20

typedef int ElemType;

typedef struct

{	

    ElemType data[MAXSIZE];	    //数组存储数据元素

	int length;                 //线性表当前长度     

}SqList;


插入算法的思路:

  • 如果插入位置不合理,抛出异常;
  • 如果线性表的长度大于等于数组长度,则抛出异常或动态增加容量;
  • 从最后一个元素开始向前遍历到第i个位置,分别将它们都向后移动一个位置;
  • 将要插入元素填入位置i处;
  • 表长加1。
/*初始条件:顺序线性表L已存在,1≤i≤ListLength(L)*/
/*操作结果: 在L中第i个位置之前插入新的数据元素e,L的长度加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++;  /*表长加1*/
    return OK;

}

删除算法思路:

  • 如果删除位置不合理,抛出异常;
  • 去除删除元素;
  • 从删除元素位置开始遍历到最后一个元素位置,分别将它们都向前移动一个位置;
  • 表长减1。
/*初始条件: 顺序线性表L已存在,1≤i≤ListLength(L)*/
/*操作结果: 删除L的第i个数据元素,并用e返回其值,L的长度减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(ilength) /*如果删除不是最后位置*/
    {
        for(k=i;klength;k++)  /*将删除位置后继元素前移*/
            L->data[k-1]=L->data[k];
    }
    L->length--; /*表长减1*/
    return OK;

}

线性表的链式存储结构:

typedef struct Node

{

	 ElemType data;

	 struct Node *next;

}Node;

typedef struct Node *LinkList;   

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

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

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

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

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

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

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

7.返回成功。

/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L), */
/* 操作结果:在L中第i个结点位置之前插入新的数
   据元素e,L的长度加1 */
Status ListInsert(LinkList *L, int i, ElemType e)
{
    int j;
    LinkList p, s;
    p = *L;
    j = 1;
    /* 寻找第i-1个结点 */
    while (p && j < i)                     
    {
        p = p->next;
        ++j;
    }
    /* 第i个结点不存在 */
    if (!p || j > i)
        return ERROR;                      
    /* 生成新结点(C标准函数) */
    s = (LinkList)malloc(sizeof(Node));    
    s->data = e;
    /* 将p的后继结点赋值给s的后继 */
    s->next = p->next;                    
    /* 将s赋值给p的后继 */
    p->next = s;                           
    return OK;
}

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

1.声明一指针p指向链表头结点,初始化j从1开始;

2.当j

3.若到链表末尾p为空,则说明第i个结点不存在;

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

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

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

7.释放q结点;

8.返回成功。

/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
/* 操作结果:删除L的第i个结点,并用e返回其
   值,L的长度减1 */
Status ListDelete(LinkList *L, int i, ElemType *e)
{
    int j;
    LinkList p, q;
    p = *L;
    j = 1;
    /* 遍历寻找第i-1个结点 */
    while (p->next && j < i)    
    {
        p = p->next;
        ++j;
    }
    /* 第i个结点不存在 */
    if (!(p->next) || j > i)
        return ERROR;           
    q = p->next;
    /* 将q的后继赋值给p的后继 */
    p->next = q->next;          
    /* 将q结点中的数据给e */
    *e = q->data;               
    /* 让系统回收此结点,释放内存 */
    free(q);                    
    return OK;
}

循环链表&双向链表

循环链表:将单链表中终端结点的指针端由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相接的单链表成为单循环链表。

双向链表:在单链表中的每个结点中,再设置一个指向其前驱结点的指针域。

你可能感兴趣的:(数据结构与算法)