线性表-数组+单链表+静态链表+循环链表+循环链表

目录

线性表

概念

ADT 

线性表的两种存储结构 

顺序存储结构【顺序映像】

 链式存储结构


线性表

n个 具有相同特性的(同一数据对象) 数据元素的有限序列 

(1)存在唯一的一个被称为“第一个”的数据元素

(2)存在唯一的一个被称为“最后一个”的数据元素

(3)除第一个之外,集合中的每个数据元素只有一个前驱

(4)除最后一个外,集合中每个数据元素只有一个后继

概念

数据项【item】记录【record】):一个数据元素可以由若干数据项组成

文件【record】:含有大量记录的线性表

直接前驱:a[i](直接前驱)领先与a[i+1]

直接后继:a[i+1](直接后继)

线性表长度:n,当n=0时,称为空表

ADT 

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;
}

 链式存储结构

用一组任意的存储单元存储线性表的数据元素

结点:包含数据域和指针域

指针域中存储的信息称作指针或链

头指针:指向头结点的位置

头节点:链表的第一个节点之前附设一个结点,称为头结点。若线性表为空表,头结点的指针域指为“空”  

单链表ADT 

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;
}

 

 

你可能感兴趣的:(数据结构学习笔记)