1.预备知识
1.学习结构体类型数据的动态储存分配
2.最好可以学懂链表基本语法
3.理解类型定义符typedef
4.理解并学会C++中引用知识
2.线性表的定义
一.前言
线性表是具有相同特性的n(n>=0)个数据元素的有限序列,通常记为:(a1,a2,…,ai-1,ai,…,an)
其中n为表长,n=0时称为空表.表中相邻元素之间存在着顺序关系
特点
- 均匀性:同一线性表的各数据元素必定有相同的数据类型和长度
- 有序性:有唯一的“第一个”和“最后一个”元素,每个元素只有一个直接前驱和一个直接后继
二.顺序表的各种操作
1.顺序表的建立
#include<stdio.h>
#define MaxSize 10
typedef struct student{
int data[MaxSize];//用静态的"数组"存放数据元素
int length;//顺序表的当前长度
}SqList; //顺序表的类型定义
void InitList(SqList& L)
{
for(int i=0;i<MaxSize;i++)
L.data[i]=0; //将所有数据元素设置为默认初始值
L.length = 0; //顺序表初始长度为0
}
bool ListInsert(SqList &L,int i,int e)
{
if(i<1||i>L.length+1) //判断i的范围是否有效
return false;
if(L.length>=MaxSize) //当前存储空间已满,不能插入
return false;
for(int j=L.length;j>=i;j--) //将第i个元素及以后的元素后移
L.data[j]=L.data[j-1];
L.data[i-1]=e; //在位置i处放入e
L.length++; //长度加1
return true;
}
/*void InitList(SqList &L,int i,int e)//该条件i的合法值在[1,length+1]
//即在线性表L中的第i个位置插入新元素e
{
for(int j=L.length;j>=i;j--) //将第i个元素及以后的元素后移
L.data[j]=L.data[j-1];
L.data[i-1]=e; //在位置i处放入e
L.length++; //长度加1
}*/
int main()
{
SqList L; //声明一个顺序表
InitList(L);//初始化顺序表
// 省略一些代码,插入几个元素
ListInsert(L,3,3);
return 0;
}
2.按位序插入(带头结点)
typedef struct LNode
{
int data;
struct LNode *next;
}LNode,*LinkList;
//按位序插入(带头结点)
bool ListInsert(LinkList &L,int i,int e)
{
if(i<1)
return false;
LNode *p; //指针p指向当前扫描到的结点
int j=0; //当前p指向的是第几个结点
p=L; //L指向头结点,头结点是第0个结点(不存数据)
while(p!=NULL&&j<i-1)//循环找到第i-1个结点
{
p=p->next;
j++;
}
if(p==NULL)
return false;
LNode *s=(LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s; //将结点s连到p之后
return true;
}
图解
3.按位序插入(不带头结点)
typedef struct LNode
{
int data;
struct LNode *next;
}LNode,*LinkList;
//按位序插入(不带头结点)
//即在线性表L中第i个位置插入新元素e
bool ListInsert(LinkList &L,int i,int e)
{
if(i<1)
return false;
if(i==1)
{
LNode *s=(LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=L;
L=s;
return true;
}
LNode *p;//指针p指向当前扫描到的结点
int j=1;//当前p指向的是第几个结点
p=L; //p指向的是第一个结点(这里是第一个结点无头结点)
while(p!=NULL&&j<i-1)//循环找到第i-1个结点
{
p=p->next;
j++;
}
if(p==NULL)
return false;
LNode *s=(LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s; //将结点s连到p之后
return true;
}
图解
4.指定结点的后插操作
typedef struct LNode
{
int data;
struct LNode *next;
}LNode,*LinkList;
//后插操作:在p结点之后插入元素e
bool InsetNextNode(LNode *p,int e)
{
if(p==NULL)
return false;
LNode *s=(LNode *)malloc(sizeof(LNode));
if(s==NULL)
return false;
s->data=e;
s->next=p->next;
p->next=s;
return true;
}
图解
5.指定结点的前插操作
typedef struct LNode
{
int data;
struct LNode *next;
}LNode,*LinkList;
//后插操作:在p结点之后插入元素e
bool InsetNextNode(LNode *p,int e)
{
if(p==NULL)
return false;
LNode *s=(LNode *)malloc(sizeof(LNode));
if(s==NULL)
return false;
s->data=e;
s->next=p->next;
p->next=s;
return true;
}
图解
6.按位序删除(带头结点)
#include<stdio.h>
#include<stdlib.h>
typedef struct LNode
{
int data;
struct LNode *next;
}LNode,*LinkList;
//按位序删除(带头结点)
//删除L的第i个数据元素,并用e返回其值,L的长度减1
bool ListDelte(LinkList &L,int i,int &e)
{
if(i<1)
return false;
LNode *p;//指针p指向当前扫描到的结点
int j=0;//当前p指向的是第几个结点
p=L; //L指向头结点,头结点是第0个结点(不存数据)
while(p!=NULL&&j<i-1)
{
p=p->next;
j++;
}
if(p==NULL)//i的值不合法
return false;
if(p->next=NULL)//第i-1个结点之后已无其他结点
return false;
LNode *q=p->next;//令q指向被删除结点
e=q->data; //用e返回元素的值
p->next=q->next;//将*q结点从链中"断开"
free(q); //释放结点的存储空间
return true; //删除成功
}
图解
3.单链表
1.单链表的按值查找
typedef struct LNode
{
int data;
struct LNode *next;
}LNode,*LinkList;
//按位查找操作.获取表L中第i个位置的元素的值
//带头结点
LNode * GetElem(LinkList L,int i)
{
if(i<0)
return NULL;
LNode *p; //指针p指向当前扫描到的结点
int j=0; //当前p指向的是第几个结点
p=L; //L指向头结点,头结点是第0个结点(不存数据)
while(p!=NULL&&j<i)//循环找到第i个结点下下
{
p=p->next;
j++;
}
return p;
}
图解
2.单链表的按位查找
#include<stdio.h>
typedef struct LNode
{
int data;
struct LNode *next;
}LNode,*LinkList;
LNode * LocateELem(LinkList L,int e)
{
LNode *p=L->next;
//从第1个结点开始查找数据域为e的结点
while(p!=NULL&&p->data!=e)
p=p->next;
return p;//找到后哦返回该结点指针,否则返回NULL
}
图解
3.求单链表的长度
#include<stdio.h>
typedef struct LNode
{
int data;
struct LNode *next;
}LNode,*LinkList;
//求表的长度
int Length(LinkList L)
{
int len=0; //统计表长2
LNode *p=L;
while(p->next!=NULL)
{
p=p->next;
len++;
}
return len;
}
图解
3.尾插法建立单链表
#include<stdio.h>
#include<stdlib.h>
typedef struct LNode
{
int data;
struct LNode *next;
}LNode,*LinkList;
//尾插法建立单链表
//初始化一个单链表(带头结点)
bool InitList(LinkList &L)
{
L=(LNode *)malloc(sizeof(LNode)); //分配一个头结点
if(L==NULL) //内存不足,分配失败
return fase;
L->next=NULL; //头结点之后暂时还没有节点
return true;
}
图解
LinkList List_Tailnsert(LinkList &L)
{
int x; //设elemtype为整型
L=(LinkList)mallloc(sizeof(LNode));
LNode *s,*r=L //r为表尾指针
scanf("%d",&x); //输入结点的值
while(x!=9999)
{
s=(LNode *)malloc(sizeof(LNode));
s->data=x;
r->next=s;
r=s; //r指向新的表尾结点
scnaf("%d",&x);
}
r->next=NULL; //尾结点指针置空
return L;
}
图解2
4.头插法建立单链表
#include<stdio.h>
#include<stdlib.h>
typedef struct LNode
{
int data;
struct LNode *next;
}LNode,*LinkList;
//头插法建立单链表
LinkList List_HeadInsert(LinkList &L){ //逆向建立单链表
//引用的本质为指针常量
LNode *s;
int x;
L=(LinkList)malloc(sizeof(LNode)); //创建头结点
L->next=NULL;//初始为空链表
scanf("%d",&x); //输入结点的值
while(x!=9999){//输入9999表示结束
s=(LNode*)malloc(sizeof(LNode)); //创建新结点
s->data=x;
s->next=L->next;
L->next=s; //将新结点插入表中,L为头结点
scanf("%d",&x);
}
}