数据结构线性表的定义与基本操作

一、线性表的一维数组静态、动态分配

1.1一维数组静态分配
静态分配
#define Maxsize 50 //定义线性表的长度
typedef struct{
    ElemType date[Maxsize]; //顺序表的元素
    int length;   			//顺序表当前的长度
}SqList;					// 使用typedef重新定义的顺序表类型
小结

1.存储空间的起始位置: 数组data,他的存储位置就是存储空间的存储位置

2线性表的最大存储容量: 数组长度MaxSize.

3.线性表当前长度: length

1.2一维数组动态分配
#define InitSize 100  //表长的初始定义
typedef struct{
    ElemType *data;   //指示动态分配数组的指针;ElemType是由typedef定义的数据元素的类型
    int length,		  //动态数组的当前长度
    	MaxSize; 	  //动态数组的最大容量
}SqlList;			//使用typedef重新定义顺序表的类型

//动态分配空间
SqlList L;
L.date = (ElemType *)malloc(InitSize*sizeof(ElemType));
小结

1.找起点: 等号左边是我们指示动态数组的指针(即L.data)

2.改反参: malloc默认返回参数是void指针,需要在malloc前面强制转换类型(即数组指针的数据类型),写法是(数据类型 *)

3.赋参: 向malloc函数赋予你想分配的内存字节数,即表长 *数组数据类型字节数(sizeof)。

总的来记的话,malloc即memory allocate(内存分配),** 分配了多少呢?** 1size of(sizeof) 数据类型乘上线性表的长度,** 这段内存指向哪呢?** 转化为数组数据类型(ElemType *),指向数组指针( *data)。

二、线性表的操作

2.1顺序表的元素插入
/*
	将元素e插入顺序表L中位序i的位置
*/
bool ListInsert(SqList &L, int i, ElemType e){
    //下标[1,L.length + 1] 合法
    if(i < 1 || i > L.length +1)
        return false;			//判断i的范围是否有效
    
    //当前存储空间已满,不能插入
    if(L.length >= Maxsize)
        retrun false;
    
    // 将第i个元素以及之后的元素后移
    if (int j = L.length;j>=i,j--)
        L.date[j] = L.data[j-1];
    //插入
    L.data[i-1] = e;
    L.length++; /表长
    return true; 
  }
小结

顺序表插入的4个步骤

1.定位置: 一个顺序表(一维数组)中的数据由相应的数组下标,插入位置如果小于第一个数据的下标或者高于最后一个数组的下标,就无法把元素插入到顺序表中。

2看空间: 顺序表存储是事先分配一段连续的内存存储单元,使用完了这段存储单元,也就没法再继续存储数据,所以插入之前要判断是否还有存储空间。

3移位置: 就像排队买车票的例子,有一个元素插入,后面的所有元素就要各自后移为这个元素腾出的空间。

4插入加表长: 将元素顺利插入到顺序表,现有的顺序表元素变多,表长也就相应的增大,所以插入结束需要将原表长相应加1。

我们可以用一首打油诗来帮助记忆:插入位置要规范((i<1||i>L.length + 1)),空间已满不可行((L.length >= MaxSize))。入表之前要移位(L.data[j] = L.data[j-1]),结束之后长加一(L.length++)。

2.2顺序存储结构删除操作
/*
	删除顺序表L中第i(1<= i <=length)个位置的元素
	e:记录删除删除元素的数据,通过引用返回。
*/
bool listDelete(SqlList &L, int i, ElemType &e){
	//非法判断;判断i的范围是否有效
    if(i<1 || i>L.length)
        return false;
    //取出需要删除的元素的数据
    e = L.data(i-1);
    
    //将第i个位置后的元素前移
    for(int j = i;j<L.length;++j){
        L.data[i-1] = L.data[j];
    }
    L.length--;
    return true;
}

我们也可以用一首打油诗来帮助记忆:删除元素要在列((i<1||i>L.length)),找准位置取出来(e = L.data[i-1])。删除空位往前移(L.data[j-1] = L.data[j]),结束之后长减一(L.length–)。

2.3顺序表的线性查找
/*
	查找顺序表中值为e的元素,如果查找成功,返回元素位序,否则返回0
*/
int LocateElem(SqList L,ElemType e){
    int i;
    for(i = 0; i<L.length: ++i)
    {
        if (L.data[i] ==e)
            return i+1;
    }
	return 0;
}

三、单链表的操作

3.1链式线性表中的插入元素
3.1.1头插法建立
  • 单链表节点类型描述
typedef struct LNode{
    ElemType data;			 //数据域
    struct LNode *next;		 //指针域,指向后继
}LNode,*LinkList;			//LinkList等价于Lnode*
  • 头插法建立单链表
LinkList createListByhead(LinkList &L){
    Lnode *s;								//工作指针
    int x;									//存输入元素			
    
    L = (LinkList)malloc(sizeof(Lnode));	//创建头结点
    L->next = NULL//初始为空表
    scanf('%d',&x);							//读取输入值
    
    while(x != 9999){							//熟读9999表示创建结束
        s = (LinkList)malloc(sizeof(Lnode));	//创建新结点
        s->data = x;							//设置数据域
        
        //插入s到表头
        s->next = L->next;					//s后继设置L
        L->next = s;							//L的后继设置s
        
        scanf('%d',&x);
    }
    return L;									//返回头结点
}

我们可以用一句话来帮助记忆:声明结点建空表(Lnode s;L->next = NULL),数值赋给数据域(s->data = x),插入头与前点间(s->next = L->next;L->next = s)。

3.1.2尾插法建立链表
Linklist createLisyByTail(LinkList &L){
	int x;								//存输入元素
    
    L = (LinkList)malloc(sizeof(LNode));	//创建头结点
    LNode *s,								//s为工作指针
    	  *r = L;							//r为表尾元素
    scanf('%d',&x);							//读取输入值
    
    while(x != 9999){
        s = (LinkList)malloc(sizeof(LNode));
        s->data = x;
        
        //插入s到表尾
        r->next = s;
        r = s;
        
        scanf('%d',&x);
    }
    
    r->next = NULL;						//尾巴置空
    return L;							// 返回头结点
    
}
3.2 单链表的查找
3.2.1按值查找结点
/*
	从头开始遍历,返回其中数据域值为给定e的结点的指针。不存在则返回NULL
*/
LNode *locateElemByValue(LinkList L,ElemType e){
    LNode *p = L->next;
    
    while(p != NULL && p->data !=e)
        p= p->netx
    return p;
}
小结

1.设置工作指针: 设置指针负责指向要访问结点的指针域,并根据指针域移动指向下一个结点。

2.循环比较数据: 将给定数据与每个结点的数据域进行比较,相同则退出循环,返回系欸但指针;否则继续访问下一个结点。

3.返回相应指针: 找到相应的结点,则返回指向该结点的指针;否则返回NULL

​整体看下来代码并不是很难,而且一句话就可以很轻松的记住:设指针(p = L->next),遍链表(p = p->next),返结点(return p)。

3.2.2 按序号查找结点值
//求有头结点的单链表长度
int length(LinkList L){
    int len = 0; 		//初始长度
    LNode *p = L->next	//去掉头结点
    
    //每向后遍历一个,长度加1
    while(p != NULL){
        len++;
        p = p->next;
    }
    return len;
}
3.3 单链表的删除和插入
3.3.1 将值单链表的第i个位置上的结点删除

我们所要做的实际上就是一步,p->next = p->next->next ,用q来取代p->next,即是:q = p->next ; p->next = p->next->next

/*
	删除第i个结点,并将数据域通过e返回,删除成功返回true,否则false
*/
bool deleteNode(LinkList L, int i,ElemType &e){
    if (i<1 || i>length(L))
        return false;
    LNode *p,				//被删除结点的前驱结点
    	  *q;				//辅助指针
	p = getElemByPos(L,i-1);//被删除结点的前驱结点
    //删除p的后继结点
    q = p->next;
    p-next = q->next;		//将需要删除的结点从链表上取下
    e = q->data;
    free(q);				//释放需要删除的结点
}
小结

1.设置辅助指针: 设置结点p,q分别用来指示要删除结点和它的前驱结点。

2.找到前驱结点: 遍历链表找到要删除结点的前驱结点

3.进行删除操作: 把要删除结点的前驱的后继变为被删除的结点的后继。

​ 可以用一句话来帮助记忆:设指针(Lnode p,q),找前驱(p = GetElem(L,i-1)),删结点(q = p->next ; p->next = p->next->next)。

3.3.2 将值为x的结点插入到单链表的第i个位置上
void insertNode(Linklist L,int i, ElemType x){
    if(i<1 || i>length(L)+1)
        return false;
    LNode *s = (LinkList)malloc(sizeof(LNode))	//创建一个新的结点
    s->data =x ;								//数据域赋值
    
    LNode *p = getElemByPos(L,i-1);				//找到第i个结点的前驱结点
   	//在p之后插入s
    s->next = p->next;
    p->next = s;
        
}
小结

1.判位置: 判断插入的位置是否在范围(if(i<1||i>Length(L)+1)

2.创结点: 如果在范围内,创建数据域为x的结点,等待插入(malloc)

3.查结点: 利用链表的插入操作插入结点。

3.4双链表的插入删除和静态链表
3.4.1 在p之后插入s和删除p的后继结点
typedef struct DNode{
    ElemType data;				//数据域
    struct DNode *prior,		//前驱指针
    			 *next;			//后继指针
}DNode,*DLinkList

请添加图片描述

插入代码
//在p之后,插入s
s->next = p->next;
p->next->prior = s;
s->prior = p;
p->next = s;

删除代码
//删除p的后继结点q
p->next = q->next;
q->next->prior = p;
free(q);
3.4.2静态链表

数组比描述的链表

#define Maxsize 50
typedef struct{
    ElemType data;		//数据域
    int next;			//指针域:下一个元素的数组下标
}SLinklist[Maxsize];

8vMOneo-1668685368094)]

插入代码
//在p之后,插入s
s->next = p->next;
p->next->prior = s;
s->prior = p;
p->next = s;

删除代码
//删除p的后继结点q
p->next = q->next;
q->next->prior = p;
free(q);
3.4.2静态链表

数组比描述的链表

#define Maxsize 50
typedef struct{
    ElemType data;		//数据域
    int next;			//指针域:下一个元素的数组下标
}SLinklist[Maxsize];
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值