线性表和链表

Posted qinmin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线性表和链表相关的知识,希望对你有一定的参考价值。

线性表的定义:
(List)

typedef int position;

typedef struct LNode* PtrToNode;
typedef PtrToNode List;

struct LNode{//数据从data[0]开始,last记录线性表中最后一个元素在表中的位置,表长为last+1;
int date[maxsize];
position last;//表空时,last = -1;
};

以下是顺序表的主要操作以及实现:
1.初始化(构造一个空表)
List MakeEmpty()
{
List L;
L = (List)malloc(sizeof(struct LNode));
L->last = -1;//表示表空
return L;
}

2.查找:在线性表中,查找与给定值x相等的数据元素。查找成功就返回X在线性表中的下标,否则返回错误信息error

#define error -1
position Find(List L, int x)
{
position i =0;//i记录下标,从0开始
while(i<=L->Last && L->date[i]!=x)
i++;
//跳出while时说明:要么i>last,要么x=date[i]
if(i>L->Last)//检查i是否越界
return error;
else
return i;
}

3.插入:在表的第i(1<=i<=n+1)个位置上插入一个值为x的元素,
将ai-an向后移动1位,再将x插入空出的序列,修改last指针.

bool insert(List L,int x,int i)
{//再位序为i的元素(下标是i_1)前插入一个元素,之后原来位序为i的元素位序就是i+1;
position j;

if(L->last==maxsize-1)
{ printf("表满");
return false;
}

if(i<1||i>last+2)
{//last是最后一个元素的下标
printf("插入位序不符合");
return false;
}

for(j = L->last;j>=i;j--)//后移元素,从后往前移动
{
L->date[j+1]=date[j];
}

L->date[i-1]=x;//第i个元素下标是i-1
L->last++;

return true;
}

4.删除:将表中位序为i(1<=i<=n)的元素删除,表长变成n-1;
元素前移,覆盖ai,再修改last;

bool delet(List L, int i)
{
position j;
if(i<1||i>L->last+1)
{
printf("位序%d不存在",i);
return false;
}

for(j=i;j<=L->last;j++)//第i个元素的下标是i-1,
{
L->date[j-1]=L->date[j];
}

L->last++;
return true;
}

单链表

definetion:
typedef struct LNode* PtrToLNode;//起个别名,注意这是一个指针类型
struct LNode{
int date;
PtrToLNode next;//next是指针类型;
}
typedef PtrToNode position;//这里的位置是结点的位置
typedef PtrToNode List;

1.求表长:
再线性表中,直接返回last+1就可以,但是再链表中要将表从头到尾遍历一遍。
p是一个移动的指针,cnt速死计数,当后面不再有结点时,cnt的值就是结点的个数.
int length(List L)
{
position p;

int cnt=0;
p = L;

while(p)//只要p不为空
{
p = p->next;
cnt++;
}

return cnt;
}

2.1 按序号查找findkth
从表的第一个结点开始遍历,直到找到第k个结点
#define error -1;


int findkth(List L)
{
position p;
int cnt = 1;
p = L;

while(p&&cnt<k)//p不为空的指针且cnt<k;
{
p=p->next;
cnt++;
}

if(cnt==k)//跳出循环时要么p为空要么cnt=k;
return p->date;
else
error;
}

2.2按值查找:从头到尾的遍历直到找到为止;
从第一个结点开始判断他的值是不是x,是就返回该结点的位置(这个位置是一个地址),否则即指向下一个结点;

#define error null;
position find(List L, int x)
{
position p =L;
while(p||p->date!=x)
{
p = p->next;
}
//跳出循环时,要么p是null,要么找到了x
if(p)//判断p是不是null
return p;
else
return error;
}

3:插入
再位序为i(1<=i<=n+1)前插入一个元素x,i为1是代表插入表头,i是n+1是代表是表尾。
若i不为1,这找到位序为i-1的结点pre;若存在,则申请一个新结点并数据域上填上相应的x的值,
然后新结点插入pre之后,返回结果链表
ps:以下代码假设没有空的头结点

#define error null;
List insert(List L, int x, int i)
{
position tmp, pre;定义两个指针

tmp = (position)malloc(sizeof(struct LNode));
tmp->date = x;//tmp是待插入的结点

if(i==1)//判断是不是第一个结点,第一个结点特殊处理
{
tmp ->next = L;
return tmp;
}
else{//查找位序为i-1的结点
int cnt =1;//位序从1开始
pre = L;
while(pre&&cnt<i-1)
{
pre = pre->next;
cnt++;
}
// 跳出while()时,要么pre为空,要么cnt = i-1
if(pre==null||cnt!=i-1)//
{
printf("所找的结点不在L中");
free(tmp);

return error;
}
else//找到了待插入结点的前一个结点
{//以下是插入代码
tmp->next = pre->next;
pre->next = tmp;
return L;
}

}
}

3.2带空的头节点的插入,不需要将插入第一个结点当作是特殊情况。
带上空的头节点的好处是:无论再哪里插入或者是删除,
L的值一直是指向固定的空结点,不会改变。

bool Insert(List L, int x, int i)
{
position tmp, pre;
int cnt =0;

pre =L;
while(pre&&cnt<i-1)//查找第i-1个结点
{
pre=p->next;
cnt++;
}

if(pre==null||cnt!=i-1)
{
printf("所查找的结点不在L中");
return false;
}
else//找到了待插入结点的前一个结点,若i为1,则pre指向表头.
{
tmp = (position)malloc(sizeof(struct LNode))
tmp ->date = x;
tmp->next = pre->next;
pre->next = tmp;
return true;
}

}

4删除
在单链表中删除指定位序为i的元素,需要找到i的前一个元素,然后再删除i

bool delete(List L, int i)
{//这里默认L右头节点
position tmp, pre;

int cnt =0;

pre = L;//pre指向头节点,,cnt从0开始计数;
while(pre&&cnt<i-1)
{
pre = pre->nexxt;
cnt++;
}

if(pre==null&&cnt!=i-1)//第i个结点的下标是i-1
{
printf("不在L中");
return false;
}
else
{
tmp = pre->next;
pre->next = tmp->next;
free(tmp);
return true;

}
}

以上是关于线性表和链表的主要内容,如果未能解决你的问题,请参考以下文章

线性表——顺序表和链表

线性表和链表

线性表和链表

线性表和链表

线性表顺序表和链表,你还分不清?

《数据结构》复习之线性表(顺序表和链表)