线性表
一.顺序表
1.顺序表的定义与基本使用
/*基本定义*/
#define Maxsize maxlen //maxlen表示线性表可能的最大数据元素数目
typedef int elmentype //elemtype表示数据元素类型,此处定义为int
typedef struct
{
elemtype data[Maxsize]; //存放线性表元素的数组
int len; //表示线性表的长度
}sqlist;
/*两种使用方法*/
sqlist L;//第一种使用方法,L就是顺序表
L.data[i]//顺序表中的第i个元素
L.len//顺序表的长度
sqlist *sq;//第二种使用方法, 定义指向顺序表的指针
sq=(sqlist *)malloc(sizeof(sqlist));//因为是指针,所以需要开辟空间
sq->data[i];//顺序表中的第i个元素
sq->len;//顺序表的长度
2.顺序表的基本操作
构造一个空的顺序线性表
void initlist(sqlist *L)
{ L-> len=0; }
//算法时间复杂度:O(1)
插入算法
思路步骤(4)
1.判断线性表的存储空间是否已满,若已满,则进行“溢出”处理(判满)
2.检查i值是否超出允许的范围(1≤i≤len+1),若超出,则进行“超出”处理(判超)
3.如果上述条件都允许,则将最后一个元素到第i个元素依次向后移动一个位置(移动)
4.将新的数据元素写到第i个位置上,线性表长度+1(写入)
int insert(sqlist *L,int i,elemtype x)//将x插入第i个位置
{
int j;
if(L->len==Maxsize)//顺序表长度等于存储最大长度则满
{
printf("溢出!\n");
return 0;
}
else if(i<1||i>L->len+1)//判断i是否超出范围
{
printf("插入位置不正确\n");
return 0;
}
else//把第i个元素和它后面的元素后移
{
for(j=L->len;j>i-1;j--)
L->data[j]=L->data[j-1];
L->data[i-1]=x;//把新元素写入下标为i-1的位置
L->len++;//顺序表长度+1
return(1);
}
//算法的最坏情况(插入第一个位置 i=1)时间复杂度:O(n)
//算法的最好情况(插入最后一个位置 i = L->len+1) 时间复杂度:O(1)
删除算法
思路步骤(3)(类似插入)
判断i值是否超出允许的范围(1≤i≤len),若是,则进行“超出范围”处理;
否则,保存第i个元素的值;
将第i个元素后的所有元素依次向前移动一个位置;
线性表长度减1,删除成功
int delete(sqlist *L,int i)//将x插入第i个位置
{
int j;
if(i<1||i>L->len+1)//判断i是否超出范围
{
printf("删除位置不正确\n");
return 0;
}
else//把第i个元素和它后面的元素前移
{
for(j=i;j<L->len-1;j--)
L->data[j-1]=L->data[j];
L->data[i-1]=x;//把新元素写入下标为i-1的位置
L->len++;//顺序表长度+1
return(1);
}
//算法的最坏情况(删除第一个位置 i=1)时间复杂度:O(n)
//算法的最好情况(删除最后一个位置 i = L->len) 时间复杂度:O(1)
求线性表的长度
int lenth(sqlist *L)
{
int len;
len=L->len;
return(len); //返回线性表的长度
}
遍历查找
int locate(sqlist *L,elemtype x)//查找顺序表中的x
{
for(int i=0;i<L->len;i++){//遍历
if(x==L->data[i])
break;
}
if(i<L->len)
return (i+1);//x是该顺序表的第i个元素
else//顺序表中不存在x
return 0;
}
二.链表
1.单链表的定义与基本使用
头结点的指针域存储链表首结点的地址
如果头结点的指针域为“空”(如图b),即L->next==NULL,表示该链表为空表
/*基本定义*/
typedef char elemtype;
typedef struct node
{ elemtype data;//数据域
struct node *next;//指针域
}Lnode,* linklist;
/*两种使用方法*/
Lnode *L; 与 linklist L; 等价
linklist h,p; //第一种,h头结点,p结点
p.data;
p.next;
Lnode *h,*p;//第二种使用方法, 定义指向头结点(h)和结点(p)的指针
p=(Lnode *)malloc(sizeof(Lnode));
h=(Lnode *)malloc(sizeof(Lnode));
(*p).data=p->data;//两种表示方法
(*p).next=p->next;
2.单链表的基本操作
头插法创建带头结点的单链表
#include <stdio.h>
#include <stdlib.h>
typedef char elemtype;
typedef struct node
{
elemtype data;
struct node *next;
}Lnode;
#define lEN sizeof(Lnode)//定义结点长度
Lnode *creat()
{
Lnode *p,*head;
head=(Lnode *)malloc(LEN);//头结点
head->next=NULL;
while(1)
{
p=(Lnode *)malloc(LEN);//申请一个新结点
scanf("%c",&p->data);//数据域赋值
p->next=h->next;//修改新结点的指针域
h->next=p;//将新结点设置为第一个结点
printf("是否继续(y/n):");
if(getchar()=='n')
break;
}
return(head);
}
尾插法创建带头结点的单链表
#include<stdio.h>
#include<stdlib.h>
typedef char elemtype;
typedef struct node{
elemtype data;
struct node *next;
}Lnode;
#define LEN sizeof(Lnode)//定义结点长度
Lnode *creat()
{
Lnode *p,*tail,*head;
tail=head=(Lnode *)malloc(LEN);//头结点
head->next=NULL;
while(1)
{
p=(Lnode *)malloc(LEN);
scanf("%c",&p->data);//数据域赋值
tail->next=p;
tail=p;
tail->next=NULL;
printf("是否继续?(y/n):");
if(getchar()=='n')
break;
}
return(head);
}
求带头结点的单链表的长度
int length(Lnode *h)
{
Lnode *p;
int i=0;
p=h->next;
while(p!=NULL)
{
++i;
p=p->next;
}
return(i);
}
单链表插入算法
int insert(Lnode *h,int i,elemtype x)
{
Lnode *p,*s;
int j;
p=H->next;
j=1;
while(P&&j<i)//寻找第i个结点
{
j++;
p=p->next;
}
if(j==i)
{
s=(Lnode *)malloc(sizeof(Lnode));
s->data=x;
s->next=p->next;
p->next=s;
return(1);
}
else
return(0);
}
单链表删除算法
//删除单链表的第i个结点
int dele(Lnode *head,int i)
{
Lnode *p,*q;
int j=1;
p=head->next;
if(p==NULL)//空表,无法删除
return 0;
while(p&&(j<i-1))
{
j++;
p=p->next;
}//寻找i-1个结点
if(j<i-1)//第i-1个结点不存在
return 0;
else if(p->next==NULL)
return 0; //第i个结点不存在
q=p->next;
p->next=q->next;
free(q);
return 1;
}
查找单链表中数据域为x的结点
Lnode *locate(Lnode *h,elemtype x)
{
Lnode *p;
p=h->next;//p为单链表的第一个结点
while(p!=NULL&&p->data!=x)//扫描整个单链表,查找值x的结点
p=p->next;//未找到,指针继续向后移扫描
return(p);
}
读取单链表中指定位置的元素
插入算法中包括此l类似算法思路
//读取单链表中的第i个元素
Lnode *get(Lnode *h,int i)
{
int j=1;
Lnode *p=h->next;
while(p&&j<i)//移动指针p,直至p为空或者p指向第i个元素
{
p=p->next;
j++;
}
if(i==j)
return(p)
else
return NULL;
}
2.循环链表(看)
定义:单链表中最后一个结点的链域值不是NULL,而是指向头结点,整个表形成一个环
特点:从表中任意结点出发均可找到表中其它的结点
操作与单链表基本一致,循环结束条件不同
带头结点的单链表:p->nextNULL
带头结点的单循环链表:p->nexthead
3.双向链表(看)
每一个结点中有两个指针域
一个指向直接后继,另一个指向直接前趋
这样的链表称为双向链表
结点描述如下:
typedef struct dulnode
{ elemtype data;
struct dulnode *next,*prior;
}Dulnode;
双向循环链表的插入算法
//改变指针链接的语句有(在双向循环链表结点p之前插入结点s
)
① s->prior=p->prior;
② p->prior->next=s;
③ s->next=p;
④ p->prior=s;
双向循环链表删除算法
//改变指针链接的语句有
p->prior->next=p->next;
p->next->prior=p->prior;
转载:https://blog.csdn.net/qq_41843893/article/details/104183033
查看评论