目录
线性表
概念
ADT
线性表的两种存储结构
顺序存储结构【顺序映像】
链式存储结构
n个 具有相同特性的(同一数据对象) 数据元素的有限序列
(1)存在唯一的一个被称为“第一个”的数据元素
(2)存在唯一的一个被称为“最后一个”的数据元素
(3)除第一个之外,集合中的每个数据元素只有一个前驱
(4)除最后一个外,集合中每个数据元素只有一个后继
数据项【item】(记录【record】):一个数据元素可以由若干数据项组成
文件【record】:含有大量记录的线性表
直接前驱:a[i](直接前驱)领先与a[i+1]
直接后继:a[i+1](直接后继)
线性表长度:n,当n=0时,称为空表
ADT List{
数据对象:D={a(i)|a(i)∈ElemSet,i=1,2,...,n,n >= 0}
数据关系:R1={|a(i-1),a(i)∈D,i = 2,...,n}
基本操作:
InitList(&L)
操作结果:构造一个空的线性表L
DestroyList(&L)
初始条件:线性表L已存在
操作结果:销毁线性表L
ClearList(&l)
初始条件:线性表L已存在
操作结果:将L重置为空表
ListEmpty(L)
初始条件:线性表L已存在
操作结果:若L为空表,则返回TRUE,否则返回FALSE
ListLength(L):
初始条件:线性表L已存在
操作结果:返回L中数据元素的个数
GetElem(L,i,&e)
初始条件:线性表L已存在,1<=i<=ListLength(L)
操作结果:用e返回L中第i个数据元素的值
LocateElem(L,e,compare())
初始条件:线性表L已存在,compare()是数据元素判定元素
操作结果:返回L中第1个与e满足关系compare()的数据元素的位序,若这样的数据元素不存在,
则返回值是0
PriorElem(L,cur_e,&pre_e)
初始条件:线性表L已存在
操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e作为他的前驱,否则操作失败,
pre_e无定义
NextElem(L,cur_e,&next_e)
初始条件:线性表L已存在
操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e作为他的后继,否则操作失
败,next_e无定义
ListInsert(&L,i,e)
初始条件:线性表L已存在,1<=i<=ListLength(L)+1
操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1
ListDelete(&L,i,&e)
初始条件:线性表L已存在,1<=i<=ListLength(L)
操作结果:删除第i个数据元素,并用e返回其值,L的长度减1
ListTraverse(L,visit())
初始条件:线性表L已存
操作结果:依次对L的每个数据元素调用函数visit()。一旦visit()失败,操作失败。
}ADT List
//线性表的顺序表示和存储结构
# include
# include
# include
# define LIST_INIT_SIZE 100//线性表存储空间的初始分配量
# define LISTINCREMENT 10//线性表存储空间的分配增量
# define ElemType int//定义数据类型
# define Status int
# define ERROR 0
# define OK 1
# define TRUE 1
# define FALSE 0
# define OVERFLOW -1
typedef struct
{
ElemType *Elem;
int Length;
int ListSize;
}SqList;
//构造一个空的线性表L
Status InitList(SqList *L)
{
L->Elem = (ElemType *)malloc(LIST_INIT_SIZE * sizeof(ElemType));
if (!*L->Elem)
{
printf("内存分配失败!\n");
exit(OVERFLOW);
return ERROR;
}
L->Length = 0;
L->ListSize = LIST_INIT_SIZE;
printf("线性表构造成功!\n");
return OK;
}
//用数组给线性表赋值
Status ListAssign(SqList *L, ElemType *Array,int length)
{
int i = 0, j = 0;
while (j < length)
{
L->Elem[j++] = Array[i++];
}
L->Length = length;
return OK;
}
//重置为空表
Status ClearList(SqList *L)
{
int i;
for (i = 0; i < L->Length; ++i)
L->Elem[i] = 0;
printf("重置成功!\n");
return OK;
}
//销毁线性表L
Status DestroyList(SqList *L)
{
if (!L)
{
printf("线性表不存在!\n");
return ERROR;
}
while (!L->Elem)
free(L->Elem);
L->Length = 0;
L->ListSize = 0;
printf("删除成功\n");
return OK;
}
//判断线性表是否为空
Status ListEmpty(SqList L)
{
if (L.Length == 0)
{
printf("线性表为空表!\n");
return TRUE;
}
else
return FALSE;
}
//返回线性表长度
Status ListLength(SqList *L)
{
if (!L)
{
printf("线性表不存在!\n");
return ERROR;
}
return L->Length;
}
//插入:在L中第i个位置之前插入新的数据元素e,L的长度加1
Status ListInsert(SqList *L, int i, ElemType e)
{
//非法插入位置
if (i < 1 || i > L->Length + 1)
{
printf("插入位置非法!\n");
return ERROR;
}
//若满,扩充数组长度
if (L->Length == L->ListSize)
{
ElemType *new_base = (ElemType *)realloc(L->Elem, (L->ListSize + LISTINCREMENT) * sizeof(Status));
if (!new_base)
{
printf("内存分配失败!\n");
exit(OVERFLOW);
return ERROR;
}
L->Elem = new_base;
L->ListSize += LISTINCREMENT;
}
//特殊情况,插入位置在最后一个
if (i == L->Length + 1)
{
L->Elem[L->Length] = e;
}
else
{
ElemType *p = NULL;
ElemType *q = &L->Elem[i - 1];
for (p = &(L->Elem[L->Length - 1]); p >= q; --p)
{
*(p + 1) = *p;
}
*q = e;
}
L->Length++;
return OK;
}
//删除 :删除第i个数据元素,并用e返回其值,L的长度减1
Status ListDelete(SqList *L, int i, ElemType *e)
{
if (i < 1 || i > L->Length)
{
printf("非法下标!\n");
return ERROR;
}
int *p = &(L->Elem[i - 1]);
*e = *p;
int *q = L->Elem + L->Length - 1;
for (++p; p <= q; ++p)
*(p - 1) = *(p);
--L->Length;
return OK;
}
//访问函数
Status visit(Status t)
{
printf("%d ", t);//由于宏定义的特殊性,修改Status值是,访问函数的输出控制符需要相应的修改
/*测试访问失败条件
if(t == 2)
return ERROR;
*/
return OK;
}
//遍历
Status ListTraverse(SqList L, Status(*visit)(ElemType e))
{
if (!&L)
{
printf("线性链表不存在!\n");
return ERROR;
}
printf("遍历数组:\n");
int i;
for (i = 0; i < L.Length; ++i)
{
if (!visit(L.Elem[i]))
{
printf("\nL.Elem[%d]访问失败!\n", i);
return ERROR;
}
}
return OK;
}
//获取cur_e的直接前驱
//若cur_e是L的数据元素,且不是第一个,则用pre_e作为他的前驱,否则操作失败,pre_e无定义
Status PriorElem(SqList L, ElemType cur_e, ElemType *pre_e)
{
int i;
for (i = 0; i < L.Length; ++i)
{
if (L.Elem[i] == cur_e)
{
break;
}
}
if (i == 0)
{
printf("cur_e是第一个元素,没有直接前驱!\n");
return ERROR;
}
if (i == L.Length)
{
printf("cur_e不存在\n");
return ERROR;
}
*pre_e = L.Elem[i - 1];
return OK;
}
//获取cur_e的直接后继
Status NextElem(SqList L, ElemType cur_e, ElemType *next_e)
{
int i;
for (i = 0; i < L.Length; ++i)
{
if (cur_e == L.Elem[i])
break;
}
if (i == L.Length)
{
printf("不存在直接后继!\n");
return ERROR;
}
*next_e = L.Elem[i + 1];
return OK;
}
//用e返回L中第i个数据元素的值
Status GetElem(SqList L, int i, ElemType *e)
{
if (ListEmpty(L))
{
return ERROR;
}
if (i < 0 || i > L.Length)
{
printf("position error!\n");
return OVERFLOW;
}
*e = L.Elem[i - 1];
}
Status compare(ElemType a, ElemType b)
{
if (a == b)
return TRUE;
else
return FALSE;
}
//查找线性链表中第一个满足compare关系的元素
Status LocateElem(SqList L, ElemType e, Status(*compare)(ElemType a, ElemType b))
{
int i;
for (i = 0; i < L.Length; ++i)
{
if (compare(e, L.Elem[i]))
{
return i + 1;
}
}
return FALSE;
}
//将所有在线性表Lb中但不在La中的数据元素插入到La中
void reunion(SqList *La, SqList Lb)
{
int La_len = ListLength(La);
int Lb_len = ListLength(&Lb);
int i, j;
ElemType e;
for (i = 0; i <= Lb_len; ++i)
{
GetElem(Lb, i, &e);
if (!LocateElem(*La, e, compare))
ListInsert(La, ++La_len, e);
}
}
//已知La,Lb中的数据元素按值非递减排列
//归并la,lb得到新的线性表Lc也满足值非递减
void MergeList(SqList La, SqList Lb, SqList *Lc)
{
InitList(Lc);
int i = 1, j = 1;
int k = 0;
int La_len = ListLength(&La), Lb_len = ListLength(&Lb);
ElemType ai, bj;
while ((i <= La_len) && (j <= Lb_len))
{
GetElem(La, i, &ai);
GetElem(Lb, i, &bj);
if (ai <= bj)
{
ListInsert(Lc, ++k, ai);
++i;
}
else
{
ListInsert(Lc, ++k, bj);
++j;
}
}
while (i <= La_len)
{
GetElem(La, i++, &ai);
ListInsert(Lc, ++k, ai);
}
while (j <= Lb_len)
{
GetElem(Lb, j++, &
bj);
ListInsert(Lc, ++k, ai);
}
}
void MergeList_Sq(SqList La, SqList Lb, SqList *Lc)
{
ElemType *pa = La.Elem, *pb = Lb.Elem;
Lc->ListSize = Lc->Length = La.Length + Lb.Length;
Lc->Elem = (ElemType *)malloc(Lc->ListSize * sizeof(ElemType));
ElemType *pc = Lc->Elem;
if (!Lc->Elem)
exit(OVERFLOW);
ElemType *pa_last = La.Elem + La.Length - 1;
ElemType *pb_last = Lb.Elem + Lb.Length - 1;
//归并
while (pa <= pa_last && pb <= pb_last)
{
if (*pa <= *pb)
*pc++ = *pa++;
else
*pc++ = *pb++;
}
//插入剩余元素
while (pa <= pa_last)
*pc++ = *pa++;
while (pb <= pb_last)
*pc++ = *pb++;
}
int main()
{
SqList list;
InitList(&list);
ElemType m, pre_m, next_m, tmp;
ElemType arr[5] = { 1,2,3,4,5 };
ListAssign(&list, arr,5);
ListTraverse(list, visit);
/*
GetElem(list, 4, &tmp);
printf("获取到的第四个元素是:%d\n",tmp);
printf("\n第一个与2满足compare关系的是:%d\n",LocateElem(list, 2, compare));
PriorElem(list,2,&pre_m);
printf("%d\n",pre_m);
NextElem(list,2,&next_m);
printf("%d\n",next_m);
GetElem(list,3,&tmp);
printf("%d\n",tmp);
//printf("%d\n",next_m);
//printf("%d\n",pre_m);
ListDelete(&list,4,&m);
printf("\n删除的元素是:%d\n",m);
ListTraverse(list,visit);
*/
return 0;
}
用一组任意的存储单元存储线性表的数据元素
结点:包含数据域和指针域
指针域中存储的信息称作指针或链
头指针:指向头结点的位置
头节点:链表的第一个节点之前附设一个结点,称为头结点。若线性表为空表,头结点的指针域指为“空”
typedef struct LNode{//节点类型
ElemType data;
struct LNode *next;
}*Line,*Position;
typedef struct{
Link head,tail;
int len;
}LinkList;
Status MakeNode(Link &p,ElemType e);
//分配p指向的值为e的结点,并返回OK;若分配失败,则返回ERROR
void FreeNode(Link &p)
//释放p所指的结点
Status InitList(Link &L)
//构造一个空的线性链表
Status DestoryList(Link &L)
//销毁线性链表L,L不再存在
Status ClearList(LinkList &L);
//将线性链表L重置为空表,并释放原链表的结点空间
Status InsFirst(Link h,Link s)
//h指向线性链表的头结点,将s所指的结插入到第一个加点之前
Status DelFirst(Link h,Link &q)
//h指向线性链表的头结点,删除链表中的第一个结点并以q返回
Status Append(LinkList &L,Link s)
//将指针s所指(彼此以指针想链)的一串结点链接在线性链表的L的最后一个结点
//之后,并改变链表的尾指针并指向新的尾结点
Status Remove(LinkLits &L,Link &q)
//删除线性链表L中的尾结点并以Q返回,改变链表L的尾指针,指向新的尾结点
Status InsBefore(LinkList &L,Link &p,Link s)
//已知p指向线性链表L中的第一个结点,将S所指向的结点插入在p所指的结点之前,并修改指针P指向新插入的结点
Status InsAfter(LinkList &L,Link &p,Link s)
//已知p指向线性链表L中的第一个结点,将S所指向的结点插入在p所指的结点之后,并修改指针P指向新插入的结点
Status SetCurElem(Link &p,ElemType e)
//已知p指向链表中的一个结点,用e更新p所指结点中数据元素的值
ElemType GetCurElem(Link p)
//已知p指向线性链表中的第一个结点,返回p所指结点中数据元素的值
Status ListEmpty(LinkList L)
//若线性链表为空表,返回TRUE,否则返回FALSE
int LinkLength(LinkList L)
//返回线性链表L中头结点的元素个数
Position GetHead(LinkList L)
//返回线性链表L中头结点的位置
Posioton GetLast(LinkList L)
//返回线性链表L中的最后一个结点的位置
Position PriorPos(LinkList L,Link p)
//已知p指向线性链表L中的一个结点,返回p所指的结点的直接前驱的位置,
//若无前驱,返回null
Poition NextPos(LinkList L,Link p)
//已知p指向线性链表L中的第一个结点,返回p所指向的直接后继的位置
//若无后继,则返回null
Status LocatePos(LinkList L,int i,Link &p)
//返回P指示线性链表L中的第i个结点的位置并返回OK,i值不合法时,返回ERROR
Status LocateElem(LinkList L,ElemType e,Status (*campare)(ElemType,ElemType))
//返回线性链表L中第一个与e满足函数compare()判定关系的元素的位置
//若不存在这样的元素,返回null
Status ListTraverse(LinkList L,Status(*visit)())
//依次对L的每个元素调用函数visit()。一旦visit()调用失败,则操作失败
// 线性链表.cpp : 定义控制台应用程序的入口点。
# include
# include
# include
# define LIST_INIT_SIZE 100//线性表存储空间的初始分配量
# define LISTINCREMENT 10//线性表存储空间的分配增量
# define ElemType int//定义数据类型
# define Status int
# define ERROR 0
# define OK 1
# define TRUE 1
# define FALSE 0
# define OVERFLOW -1
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode,*LinkList,*Position,*pNode;
//创建节点
Status MakeNode(LinkList *Node, ElemType e)
{
*Node = (LinkList)malloc(1 * sizeof(LNode));
if (!Node)
{
//内存分配失败!
exit(OVERFLOW);
}
(*Node)->data = e;
return OK;
}
//删除Node所指向的节点
Status FreeNode(pNode p)
{
free(p);
return OK;
}
//初始化线性链表
Status InitList(LinkList *L)
{
*L = (LinkList)malloc(1 * sizeof(LNode));
if (!(*L))
return ERROR;
return OK;
}
//重置线性链表
Status ClearList(LinkList *L,ElemType e)
{
if (!(*L))
{
printf("线性链表为空!");
return ERROR;
}
LinkList p, q;
p = *L;
while (p)
{
p->data = e;
p = p->next;
}
return OK;
}
//返回头结点指针
Position GetHead(LinkList L)
{
if (!L)
{
printf("链表不存在!\n");
return ERROR;
}
return L->next;
}
//返回尾结点位置
Position GetLast(LinkList L)
{
if (!L)
{
printf("链表不存在!\n");
return ERROR;
}
Position p = NULL;
for (p = L->next; p && p->next; p = p->next);
return p;
}
//在h所指向的头结点之前插入s所指向的节点
Status InsFirst(LinkList *L, pNode s)
{
Position Head = GetHead(*L);
s->next = Head;
(*L)->next = s;
/*1 10 2 3
s->next = Head->next;
Head->next = s;*/
return OK;
}
//删除h指向的头结点,节点位置返回到q指针
Status DelFirst(LinkList *L, pNode *q)
{
Position Head = GetHead(*L);
(*L)->next = Head->next;
*q = Head;
pNode p = (pNode)malloc(1 * sizeof(LNode));
*p = *Head;
FreeNode(p);
return OK;
}
//将指针s所指的一串节点链接在L的最后
Status Append(LinkList *L, pNode s)
{
Position Tail = GetLast(*L);
Tail->next = s->next;
return OK;
}
//删除尾节点,并以q返回
Status Remove(LinkList *L, LNode *q)
{
if (!L)
{
printf("链表不存在!\n");
return ERROR;
}
Position Tail = GetLast(*L);
pNode p = *L;
while (p && p->next != Tail)
{
p = p->next;
}
p->next = NULL;
*q = *Tail;
FreeNode(Tail);
return OK;
}
//已知p指向链表中的一个节点,将s所指向的节点插入在p所指节点之前
Status InsBefore(LinkList *L, pNode p, pNode s)
{
pNode q = (*L)->next;
while (q && q->next != p)
{
q = q->next;
}
s = q->next;
q->next = s;
return OK;
}
//已知P指向链表中的一个节点,将s指向的节点插入在所指节点之后
Status InsAfter(LinkList *L, pNode p, pNode s)
{
s->next = p->next;
p->next = s;
return OK;
}
//销毁线性链表
Status DestoryList(LinkList *L)
{
if (!(*L))
return ERROR;
LinkList p, q;
p = (*L)->next;
while (p)
{
q = p->next;
free(p);
p = q;
}
(*L)->next = NULL;
return OK;
}
//逆位序输入n个元素的值,建立带头节点的单链线性表(带头结点)
Status CreateList_n(LinkList *L, int n)
{
int i;
LinkList p;
*L = (LinkList)malloc( 1 * sizeof(LNode));
if (!L)
{
printf("内存分配失败!\n");
exit(OVERFLOW);
}
(*L)->next = NULL;
printf("输入链表数据:\n");
while(n--)
{
p = (LinkList)malloc(1 * sizeof(LNode));
if (!p)
{
printf("内存分配失败!\n");
exit(OVERFLOW);
}
scanf_s("%d",&p->data);
p->next = (*L)->next;
(*L)->next = p;
}
return OK;
}
//正位序创建线性单链表(带头结点)
Status CreateList_p(LinkList *L, int n)
{
//L是链表的头指针
LinkList p = NULL, q = NULL;
InitList(L);
if (!L)
{
exit(OVERFLOW);
}
(*L)->next = NULL;
q = *L;//指向当前节点
ElemType e;
for (int i = n; i>0; i--)
{
scanf_s("%d",&e);
MakeNode(&p, e);
q->next = p;//若变为q = p则为无头结点的链表
q = q->next;
}
p->next = NULL;
return OK;
}
//返回链表长度
int ListLength(LinkList L)
{
int sum = 0;
LinkList p = L->next;
while (p)
{
sum++;
p = p->next;
}
return sum;
}
//获取第i个节点数字的值,赋给e
Status GetElem(LinkList L, int i, ElemType *e)
{
LinkList p = L;
int j = 0;
while (p && j < i)
{
p = p->next;
j++;
}
if (!p || j > i)
return ERROR;
*e = p->data;
return OK;
}
//单链表插入
Status ListInsert(LinkList *L, int i, ElemType e)
{
LinkList p = *L;
int j = 0;
while (p && j < i - 1)
{
p = p->next;
j++;
}
if (!p || j > i - 1)
return ERROR;
LinkList s = (LinkList)malloc(1 * sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return OK;
}
//单链表删除
Status ListDelete(LinkList *L, int i, ElemType *e)
{
LinkList p = *L;
int j = 0;
while (p->next && j < i - 1)
{
p = p->next;
++j;
}
if (!(p->next) || j > i - 1)
return ERROR;
LinkList q = (LinkList)malloc(1 * sizeof(LNode));
q = p->next;
p->next = q->next;
*e = q->data;
free(q);
return OK;
}
//用e更新节点所指向的节点的数值,一直p是线性链表中的一个结点
Status SetCurElem(LNode *p, ElemType e)
{
p->data = e;
return OK;
}
//大于等于关系
Status compare(ElemType a, ElemType b)
{
if (a >= b)
return OK;
else
return ERROR;
}
//返回链表中L中第一个与e满足compare关系的元素的位置
Position LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType a, ElemType b))
{
Position p = L->next;
while (p)
{
if (compare(p->data, e))
break;
p = p->next;
}
if (p == NULL)
return NULL;
return p;
}
//返回 P指向的链表中第i个位置的节点,并返回OK,如果i值不合法,返回ERROR
Status LocatePos(LinkList L, int i, LNode *p)
{
if (i >= ListLength(L) || i == 0)
{
printf("超出合理返回!\n");
return ERROR;
}
int j = 0;
LNode* q = L->next;
while (j < i)
{
q = q->next;
j++;
}
*p = *q;
return OK;
}
//已知p指向线性表中的一个结点,返回前驱结点
Position PriorPos(LinkList L, pNode p)
{
Position Head = GetHead(L);
if (p == Head)
{
printf("没有前驱!\n");
return NULL;
}
pNode q = Head;
while (q->next != p)
{
q = q->next;
}
return q;
}
//已知p指向链表的一个节点,返回p所指向的直接后继的位置
Position NextPos(LinkList L, pNode p)
{
Position Tail = GetLast(L);
if (p == Tail)
{
printf("直接后继不存在!\n");
return NULL;
}
return p->next;
}
//判断数组是否为空
Status ListEmpty(LinkList L)
{
if (ListLength(L) == 0)
{
return OK;
}
return ERROR;
}
//访问函数
Status visit(ElemType e)
{
printf("%d ",e);
return OK;
}
//遍历链表,访问visit函数
Status ListTraverse(LinkList L,Status(*visit)(ElemType e))
{
if (!L)
{
printf("链表不存在!\n");
return ERROR;
}
if (ListEmpty(L))
{
printf("空链表!\n");
return ERROR;
}
LinkList p = L->next;
while (p)
{
if (!visit(p->data))
{
return ERROR;
}
p = p->next;
}
printf("\n");
return OK;
}
//输出某个确定节点的值
Status ShowData(LinkList L,int i)
{
if (i <= 0)
return FALSE;
int j;
for (j = 0; j < i; ++j)
{
L = L->next;
}
printf("%d ",L->data);
return OK;
}
//两个链表去重合成
void MergeList(LinkList *La, LinkList *Lb, LinkList *Lc)
{
//已知单链线性表La,Lb的元素按值非递减的顺序排列
//归并La和Lb得到新的单链线性表Lc,Lc的元素也按照值递减的顺序排列
LinkList pa = (*La)->next;
LinkList pb = (*Lb)->next;
Lc = La;
LinkList pc = *La;
while (pa && pb)
{
if (pa->data <= pb->data)
{
pc->next = pa;
pc = pa;
pa = pc->next;
}
else
{
pc->next = pb;
pc = pb;
pb = pb->next;
}
}
pc->next = pa ? pa : pb;
free(Lb);
}
int main()
{
LinkList List = NULL;
int i,m,len;
/*
LinkList list = NULL;
CreateList_n(&list, 3);
printf("逆序输出链表:\n");
for(i = 0;i < 3;++i)
ShowData(list, i+1);
*/
printf("输入链表长度\n");
scanf_s("%d",&len);
printf("输入线性链表的值:\n");
CreateList_p(&List,len);
printf("遍历链表:\n");
ListTraverse(List,visit);
/*
Position next = NextPos(List,GetHead(List));
printf("首节点的直接后继是:\n");
printf("%d\n",next->data);
Position pre = PriorPos(List, GetLast(List));
printf("尾结点的前驱是:\n");
printf("%d\n",pre->data);
LNode tail;
Remove(&List, &tail);
printf("删除的元素是:%d",tail.data);
printf("\n");
printf("遍历链表:\n");
ListTraverse(List, visit);
LinkList s = NULL;
printf("输入新增链长度:\n");
scanf_s("%d",&len);
printf("新增的链是:\n");
CreateList_p(&s, len);
Append(&List, s);
printf("遍历链表:\n");
ListTraverse(List, visit);
LNode anew;
anew.data = 10;
anew.next = NULL;
InsFirst(&List, &anew);
printf("遍历链表:\n");
ListTraverse(List, visit);
pNode del;
DelFirst(&List, &del);
printf("遍历链表:\n");
ListTraverse(List, visit);
Position tail = GetLast(List);
printf("尾节点的值为:%d\n",tail->data);
LNode p;
LocatePos(List, 2, &p);
printf("第2位数据是:\n%d",p.data);
ElemType pos_data;
printf("输入判断数据:\n");
scanf_s("%d", &pos_data);
Position pos = LocateElem(List, pos_data, compare);
if (pos)
printf("%d\n", pos->data);
else
printf("数据不存在\n");
printf("顺序输出链表:\n");
for (i = 0; i < len; ++i)
ShowData(List, i + 1);
printf("\n链表长度:%d",ListLength(List));
ClearList(&List, 0);
printf("\n清空数组:\n");
for (i = 0; i < 3; ++i)
ShowData(List, i + 1);
ListDelete(&List, 2, &m);
printf("\n删除的元素是:%d\n",m);
printf("删除后链表:\n");
for (i = 0; i < 2; ++i)
ShowData(List, i + 1);
GetElem(List,2,&m);
printf("%d\n",m);
ListInsert(&List, 2, 2);
printf("\n插入后链表:\n");
for (i = 0; i < 4; ++i)
ShowData(List, i + 1);
*/
return 0;
}
用数组代替值代表指针域
# include
# include
# include
# define OK 1
# define FALSE 0
# define OVERFLOW -1
# define Status int
# define ElemType int
# define ERROR -1
# define MAXSIZE 1000 //链表的最大长度
typedef struct
{
ElemType data;
int cur;
}component,SLinkList[MAXSIZE];
//将一维数组space各分量链成一个备用链表,space[0].cur作为头指针
//"0"表示空指针
void InitSpace(SLinkList space)
{
int i;
for (i = 0; i < MAXSIZE - 1; ++i)
space[i].cur = i + 1;
space[MAXSIZE - 1].cur = 0;
}
//从备用链表中取第一个空闲节点,返回下标
int Malloc(SLinkList space)
{
int i = space[0].cur;
if (space[0].cur)
{
space[0].cur = space[i].cur;
}
return i;
}
//将下标为k的空闲节点回收到备用链表中
void Free(SLinkList space,int k)
{
space[k].cur = space[0].cur;
space[0].cur = k;
}
//求链表 的长度
int ListLength(SLinkList space)
{
int amount = 0,i = 0;
while (space[i].cur)
{
i = space[i].cur;
++amount;
}
return amount;
}
//插入
Status ListInsert(SLinkList L, int i, ElemType e)
{
int j,k,l;
k = MAXSIZE - 1;//L[k].cur = 1
if (i < 1 || i > ListLength(L) + 1)
return ERROR;
j = Malloc(L);
if (j)
{
L[j].data = e;
for (l = 1; l <= i - 1; ++l)
{
k = L[k].cur;//1->i-1
}
L[j].cur = L[k].cur;
L[k].cur = j;
return OK;
}
else
return ERROR;
}
//删除并赋值
Status ListDelete(SLinkList L, int i, ElemType *e)
{
int j, k;
if (i < 1 || i > ListLength(L))
return ERROR;
k = MAXSIZE - 1;
for (j = 1; j <= i - 1; ++j)
{
k = L[k].cur;//0->i-1
}
j = L[k].cur;
L[k].cur = L[j].cur;
*e = L[j].data;
Free(L, j);
return OK;
}
//遍历输出
void ListPrint(SLinkList L)
{
int i = L[MAXSIZE - 1].cur;//指向第一个
while (i != 0)
{
printf("%d ", L[i].data);
i = L[i].cur;
}
printf("\n");
}
//
int LocateElem(SLinkList L, ElemType e)
{
int i = L[0].cur;
while (i && L[i].data != e)
{
i = L[i].cur;
}
return i;
}
void difference(SLinkList L, int *S)
{
InitSpace(L);
*S = Malloc(L);//S指向结果链表的头节点
int *r = S;//尾指针:指向链表尾部
int m, n,i,j,b,k;
scanf_s("%d%d",&m,&n);//m,n分别表示两个集合的数量
//输入第一个集合的元素
for (j = 1; j <= m; ++j)
{
i = Malloc(L);//分配节点
scanf_s("%d",L[i].data);
L[*r].cur = i;//将i连接到链表
*r = i;//将尾指针指向i
}
L[*r].cur = 0;//尾部设为空
for (j = 1; j <= n; ++j)//输入第二个集合的n个元素
{
scanf_s("%d", &b);
int *p = S;//p指向头指针;只是为了存在时候使用,与k同步
k = L[*S].cur;//k从头结点开始遍历
while (k != L[*r].cur && L[*S].data != b)//遍历条件:未到达节点尾部;元素是否存在于链表中
{
*p = k;
k = L[k].cur;
}
//若不存在与链表中,插入
if (k == L[*r].cur)
{
i = Malloc(L);
L[i].data = b;
L[i].cur = L[*r].cur;
L[*r].cur = i;
}
else//若存在,将该元素删除
{
L[*p].cur = L[k].cur;
Free(L, k);
if (*r == k)
r = p;//若删除的是r所指节点,则需修改尾指针
}
}
}
int main()
{
SLinkList list;
ElemType m;
InitSpace(list);
ListPrint(list);
int i;
for (i = 0; i <= 3; ++i)
{
ListInsert(list,i,i*10);
}
ListPrint(list);
printf("%d\n",LocateElem(list,20));
for (i = 1; i <= 3; ++i)
{
ListDelete(list, 1, &m);
printf("删除元素:%d\n",m);
}
return 0;
}
循环链表的结构和单链表结构一样
单链表尾结点的指针由空指针改为指向头结点,就使整个单链表形成一个环,
这种头尾相接的单链表称为循环单链表,简称循环链表。表中最后一个结点的指针域指向头结点,整个链表形成一个环
# include
# include
# include
# define OK 1
# define ERROR 0
# define TRUE 1
# define FALSE 0
# define END 0
# define OVERFLOW -1
# define ElemType int
# define Status int
typedef struct CLinkNode
{
ElemType data;
struct CLinkNode *next;
}CLinkNode,*CLinkList;
//初始化循环链表
Status InitCLinkList(CLinkList *list)
{
if (list == NULL)
return ERROR;
int data;
CLinkNode *target = NULL;//寻找尾结点位置
CLinkNode *head_node = NULL;//存储头结点位置
printf("输入链表的值,0表示结束初始化:\n");
while (1)
{
scanf_s("%d", &data);
//判断是否为初始化结束标志
if (data == 0)
break;
//判断list是否为空链表
//若为空,创建头指针指向的头结点
//不为空,找到尾结点,插入到 尾结点之后,并将其指向头节点
if (*list == NULL)
{
//创建头指针
CLinkNode *head = (CLinkNode *)malloc(1 * sizeof(CLinkNode));
if (head == NULL)
{
printf("内存分配失败!\n");
exit(OVERFLOW);
}
*list = head;
//创建头结点
CLinkNode *node = (CLinkNode *)malloc(1 * sizeof(CLinkNode));
if (node == NULL)
{
printf("内存分配失败!\n");
exit(OVERFLOW);
}
node->data = data;
node->next = head;//头结点指向头指针
head->next = node;//头指针指向头节点
}
else
{
//找到尾结点位置,插入到尾结点之后
for (target = (*list)->next; target->next != *list; target = target->next);
head_node = target->next;
CLinkNode *node = (CLinkNode*)malloc(1 * sizeof(CLinkNode));
if (!node)
{
printf("内存分配失败!\n");
exit(OVERFLOW);
}
node->data = data;
node->next = head_node;
target->next = node;
}
}
return OK;
}
//访问函数
void visit(ElemType e)
{
printf("%d ",e);
}
//遍历链表
Status TraverseCLinkList(CLinkList list, void(*visit)(ElemType e))
{
if (list == NULL)
{
printf("链表不存在!\n");
exit(OVERFLOW);
}
CLinkNode *target = NULL;
for (target = list->next; target->next != list; target = target->next)
{
visit(target->data);
}
visit(target->data);
printf("\n");
return OK;
}
//获取链表长度
Status LengthCLinkList(CLinkList list)
{
int len = 0;
CLinkNode *target = NULL;
for (target = list->next; target != list; target = target->next)
{
len++;
}
return len;
}
//在指定位置插入节点
Status InsertCLinkList(CLinkList *list, int i, ElemType e)
{
if (i < 1 || i - 1 > LengthCLinkList(*list))
{
printf("输入位置不合法!\n");
return ERROR;
}
int j = 1;
CLinkNode *target = NULL;
//寻找插入位置的前一个节点
for (target = (*list)->next; j < i-1 && target != (*list); target = target->next,++j);
CLinkNode *node = (CLinkNode *)malloc(1 * sizeof(CLinkNode));
if (!node)
{
printf("内存分配失败!\n");
exit(OVERFLOW);
}
node->data = e;
node->next = target->next;
target->next = node;
return OK;
}
//删除指定位置的节点
Status DeleteCLinkList(CLinkList list, int i, ElemType *e)
{
if (!list)
{
printf("链表不存在!\n");
return ERROR;
}
if (i < 0 || i > LengthCLinkList(list))
{
printf("输入位置不合法\n");
return ERROR;
}
CLinkNode *target = NULL;
int j = 1;
//找到删除节点的前一个位置
for (target = list->next; j < i-1 && target != list; target = target->next, ++j);
CLinkNode *del_node = target->next;
*e = del_node->data;
target->next = del_node->next;
free(del_node);//不能直接释放指向链表中节点的指针,只能释放指向节点的指针
return OK;
}
//compare()函数
bool compare(ElemType a, ElemType b)
{
return a ==b;
}
//获取链表中与e满足compare关系的第一个节点的位置【索引】
Status LocateElem(CLinkList list, int e, bool(*compare)(ElemType a, ElemType b))
{
if (!list)
{
printf("链表不存在!\n");
return ERROR;
}
int i = 0;
CLinkNode *target = NULL;
for (target = list->next; target->next != list; target = target->next)
{
i++;
if (compare(e, target->data))
break;
}
if (i == 0)
{
printf("%d在链表中不存在\n",e);
return ERROR;
}
return i;
}
//获取第i个节点为的数据
Status LocatePos(CLinkList list, Status i,ElemType *e)
{
if (!list)
{
printf("线性链表不存在\n");
return ERROR;
}
if (i < 1 || i > LengthCLinkList(list))
{
printf("输入位置不合法\n");
return ERROR;
}
int j = 1;
CLinkNode *target = NULL;
//寻找节点位置
for (target = list->next; j < i && target->next != list; target = target->next,j++);
*e = target->data;
return OK;
}
int main()
{
CLinkList list = NULL;
InitCLinkList(&list);
printf("遍历链表元素:\n");
TraverseCLinkList(list, visit);
/*
ElemType data;
LocatePos(list, 2, &data);
printf("第二个节点的数据是:%d\n",data);
int data;
scanf_s("%d",&data);
printf("%d的位置是:%d\n",data,LocateElem(list,data,compare));
//printf("链表长度为:%d\n",LengthCLinkList(list));
int pos, data;
printf("输入插入位置:\n");
scanf_s("%d",&pos);
printf("输入插入数据:\n");
scanf_s("%d",&data);
InsertCLinkList(&list, pos, data);
printf("遍历链表元素:\n");
TraverseCLinkList(list, visit);
printf("输入删除位置:\n");
scanf_s("%d", &pos);
DeleteCLinkList(list, pos, &data);
printf("删除元素是:%d\n",data);
printf("遍历链表元素:\n");
TraverseCLinkList(list, visit);
*/
return 0;
}
两个指针,一个指向前驱,一个指向后继
# include
# include
# include
# define OK 1
# define ERROR 0
# define TRUE 1
# define FALSE 0
# define END 0
# define OVERFLOW -1
# define ElemType int
# define Status int
typedef struct DuLNode
{
ElemType data;
struct DuLNode *prior, *next;
}DuLNode,*DuLinkList;
Status InitDuLinkList(DuLinkList *list)
{
DuLNode *head = (DuLNode *)malloc(1 * sizeof(DuLNode));
if (!head)
{
printf("内存分配失败!\n");
return ERROR;
}
*list = head;
ElemType data;
DuLNode *target = head;
target->prior = NULL;
target->next = NULL;
printf("输入链表数据,0表示输入结束\n");
while (1)
{
scanf_s("%d",&data);
if (data == 0)
break;
DuLNode *node = (DuLNode *)malloc(1 * sizeof(DuLNode));
node->data = data;
node->next = NULL;
node->prior = target;
target->next = node;
target = node;
}
return OK;
}
//访问函数
void visit(ElemType e)
{
printf("%d", e);
}
//遍历链表
Status TraverseDuLinkList(DuLinkList list, void(*visit)(ElemType e))
{
if (!list)
{
printf("链表不存在!\n");
exit(OVERFLOW);
}
DuLNode *target = list->next;
for (; target != NULL; target = target->next)
{
visit(target->data);
if(target->next != NULL)
printf("<-->");
}
printf("\n");
return OK;
}
//头插法
Status InsertDuLinkListHead(DuLinkList *list,ElemType e)
{
DuLNode *node = (DuLNode *)malloc(1 * sizeof(DuLNode));
node->data = e;
node->next = (*list)->next;
node->prior = *list;
(*list)->next = node;
return OK;
}
//尾插法
Status InsertDuLinkListTail(DuLinkList *list, ElemType e)
{
DuLNode *node = (DuLNode *)malloc(1 * sizeof(DuLNode));
node->data = e;
node->next = NULL;
DuLNode* target = (*list)->next;
while (target->next)
{
target = target->next;
}
target->next = node;
node->prior = target;
return OK;
}
//插入节点
Status InsertDuLinkList(DuLinkList *list, int i, ElemType e)
{
if (!(*list))
{
printf("链表不存在!\n");
return ERROR;
}
DuLNode *target = (*list)->next;
int j = 1;
while (j < i - 1)
{
target = target->next;
}
DuLNode *node = (DuLNode *)malloc(1 * sizeof(DuLNode));
if (!node)
{
printf("内存分配失败!\n");
return ERROR;
}
node->data = e;
node->next = target->next;
node->prior = target;
target->next = node;
return OK;
}
//删除节点
Status DeleteDuLinkList(DuLinkList *list, int i , ElemType *e)
{
if (!(*list))
{
printf("链表不存在!\n");
return ERROR;
}
DuLNode *target = (*list)->next;
int j = 1;
while (j < i - 1)
{
target = target->next;
j++;
}
DuLNode *del_node = target->next;
*e = del_node->data;
target->next = del_node->next;
del_node->next->prior = target;
free(del_node);
return OK;
}
//长度函数
Status LengthDuLinkList(DuLinkList list)
{
int len = 0;
DuLNode *target = list->next;
while (target)
{
len++;
target = target->next;
}
return len;
}
bool compare(ElemType a, ElemType b)
{
return a == b;
}
//获取链表中与e满足compare关系的第一个节点的位置【索引】
Status LocateElem(DuLinkList list, int e, bool(*compare)(ElemType a, ElemType b))
{
if (!list)
{
printf("链表不存在!\n");
return ERROR;
}
int i = 0;
DuLNode *target = NULL;
for (target = list->next; target->next != list; target = target->next)
{
i++;
if (compare(e, target->data))
break;
}
if (i == 0)
{
printf("%d在链表中不存在\n", e);
return ERROR;
}
return i;
}
//获取第i个节点为的数据
Status LocatePos(DuLinkList list, Status i, ElemType *e)
{
if (!list)
{
printf("线性链表不存在\n");
return ERROR;
}
if (i < 1 || i > LengthDuLinkList(list))
{
printf("输入位置不合法\n");
return ERROR;
}
int j = 1;
DuLNode *target = NULL;
//寻找节点位置
for (target = list->next; j < i && target->next != list; target = target->next, j++);
*e = target->data;
return OK;
}
int main()
{
DuLinkList list;
ElemType data;
InitDuLinkList(&list);
printf("遍历链表\n");
TraverseDuLinkList(list, visit);
printf("链表长度是:%d\n", LengthDuLinkList(list));
LocateElem(list, 2, compare);
/*
InsertDuLinkList(&list, 2, 4);
printf("遍历链表\n");
TraverseDuLinkList(list, visit);
DeleteDuLinkList(&list, 2, &data);
printf("遍历链表\n");
TraverseDuLinkList(list, visit);
*/
return 0;
}