数据结构复习(一)线性表概念和基本操作

线性表的基本概念

线性表的定义与基本操作

  1. 相同有限数据元素构成的有限序列,线性表是一种逻辑结构,顺序表(数组)和链表是存储结构
//静态数组
# define MaxSize 50
struct SqList{
   ElemType data[MaxSize];
   int length;
};
//动态数组
# define InitSize 50
struct SeqList{
  ElemType* data;
  int length,Maxsize;
  //因为这里是动态创建的,只知道初始长度
  //需要确定其最大的长度因为是有限的 
};

//需要动态创建
SeqList L;
L.data = new int[InitSize];

  1. 基本操作
    需要真正对表进行修改的则需要传入&L,否则直接按值传递
bool InitList(&L);//初始化
int Length(L);//返回长度
int LocateElem(L,e);//返回值为e的元素的位置
ElemType GetElem(L,i);//返回i位置的元素值
bool ListInsert(&L,i,e);//在i位置插入元素
bool ListDelete(&L,i,&e);//删除i位置的元素,返回到e
void PrintList(L);//打印L中的元素
bool Empty(L);//判断线性表是否为空
bool DestoryList(&L);//销毁线性表
//简单实现
bool ListInsert(SqList &L,int i ,ElemType e){
if(i<1&&i>length+1)//这里是length+1但是不能是其他,因为可以加在当前list的尾部,这里指的是顺序表的位序
  return false;
if(L.length>=MaxSize)//当前存储空间已满,不能插入
  return false;
for(int j=L.length;j>=i;j--)//这里是线性表的下标
  L.data[j]=L.data[j-1];
L.data[i-1]=e;
L.length++;
return true;

注意:凡是涉及到位置的都要先判断一下位置是否合理,然后涉及到实际位置(索引)和线性表本身的顺序不一致,需要注意一下

线性表的链式表示

单链表

  1. 节点类型
typedef struct LNode{
   ElemType data;
   struct LNode* next;
}LNode ,*LinkList;
  1. 头指针
    始终设置一个指针指向第一个节点,通常用来标识一个单链表
  2. 头节点
    头节点通常里面不存任何信息,也可以存储一些表长等信息。
    头节点有两个优点:
    a、因为头节点的指针域指向第一个节点,所以正常的第一个节点和其他所有节点的所有操作都一致了,因为不需要对头指针进行改变了
    b、无论链表是否为空,头指针都指向头节点,这样非空链表和空链表的处理方式就一致了

单链表的基本操作
1. 插入方法

头插法
首先创立头节点,然后使用不断生成新节点挂在头节点的后面,生成链表的元素顺序和输入数据的顺序相反

LinkList CreateList1(LinkList &L){//已经传入L,后面直接分配空间即可

LNode * s;
int x;
L=(LinkList)malloc(sizeof(LNode));
L->next = NULL;
cin>>x;

while(x!=9999){
   s = (LinkList)malloc(sizeof(LNode));
   s->data = x;
   s->next = L->next;
   L->next = s;
   cin>>x;
 }
return L;

尾插法
尾插法必须增加一个指针始终指向当前链表的尾部,这样才能知道下一个元素插入到哪里

LinkList CreateList2(LinkList &L){

  L = (LinkList)malloc(sizeof(LNode));
  L -> next = NULL;
  LNode *r=L,*s;
  int x; 
  cin>>x;
 while(x!=9999){
  s = (ListNode)malloc(sizeof(LNode));
  s->data = x;
 // s->next = NULL;如果最后直接在外面进行一次置NULL,这里就不用置NULL了
  r->next = s;
  r = s;
  cin>>x;
}
r->next = NULL;
return L;
}
2. 按序号查找节点
LNode *GetElem(LinkList L,int i){
  int j = 1;
  LNode *p = L->next;
  if (i == 0)
  return L;
  if (i<1)
  return NULL;
  while(j!=i){
   p=p->next;
   j++;
  }
  return p;
}
3. 按值查找节点
LNode* LocateElem(LinkList L,ElemType e){
 LNode* p = L->next;
 while( p!=NULL&&p->data!=e){
 p=p->next;
}
return p;//没找到就是NULL不可能是其他的值,因为一定会到末尾
}
4. 插入节点操作

分为前插和后插,一般采用的是后插操作

p = GetElem(L,i-1);
s->next = p->next;
p->next = s;

前插操作:(两种方法)

  1. 使用GetElem方法找到第i-1个节点,然后使用后插操作
  2. 仍然使用后插操作,但是将后插后的节点数值与插入节点之前的节点数值进行一次交换
s->next = p->next;
p->next = s;
temp = p->data;
p->data = s->data;
s->data = temp;
5. 删除节点操作

删除操作(2种方法)

  1. 查找到被删节点的前驱节点,然后执行删除操作
p = GetElem(L,i-1);
q = p->next;
p->next = q->next;
free(q);
  1. 删除当前节点可以用删除当前节点的后继节点来操作,将后继节点的值赋值给前面节点,然后直接删除后继
q = p->next;
p->data= p->next->data;
p->next = q->next;
free(q);

双链表

typedef struct DNode{
    ElemType data;
    struct DNode *prior,*next;
}DNode,*DLinkList;

循环链表

  1. 循环单链表
    最后一个节点的next域不指向NULL,指向头指针,判空条件:头节点的指针域是否为头节点
  2. 循环双链表
    循环双链表的处理注意prior和next节点都要保证循环指向,判空条件:prior和next都指向L

静态链表

借助数组来描述线性表的链式存储结构,节点也有data和next域,但是这里的指针是节点的相对地址(数组下标),同静态数组一样也要预先分配一个空间

# define MaxSize 50
typedef struct{
 ElemType data;
 int next;
}SLinkList[MaxSize];

静态链表以-1为终点结束

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值