数据结构之线性表(三)

目录

1.循环单向链表

1.1 定义

1.2 基本操作

1.3 代码实现

1.3.1 初始化

1.3.2 求表长

1.3.3 判空

1.3.4 整表创建 头插法

1.3.5 遍历输入

1.3.6 整表清除

1.3.7 整表创建 头插法

1.3.8 插入

1.3.9 按位查找

1.3.10 按值查找

1.3.11 删除

 1.4 完整代码

2.循环双向链表 

2.1 定义

2.2 基本操作

2.3 代码实现

2.3.1 初始化

2.3.2 求表长

2.3.3 判空

2.3.4 整表创建 尾插法

2.3.5 遍历

2.3.6 整表清空

2.3.7 插入

​编辑2.3.8 按位查找

​编辑2.3.9 按值查找

​编辑2.3.10 删除

2.4 双向循环链表的完整代码实现


tips:本章节讲述 循环单向链表 与 循环双向链表!!!

1.循环单向链表

1.1 定义

        循环单链表单链表的区别在于,表中最后一个结点的指针不是NULL,而是改为指向头结点,从而整个链表形成一个环。

        在循环单链表中,表尾结点的指针域指向L,故表中没有指针域为NULL的结点,因此循环单链表的判空条件不是头结点的指针是否为空,而是它是否等于头指针

        在单链表中只能从表头结点开始往后顺序遍历整个链表,而循环单链表可以从表中的任意一个结点开始遍历整个表。有时对单链表常做的操作是在表头和表尾进行的,此时对循环单链表不设头指针而仅设尾指针,从而使得操作的效率更高。其原因是,若设的是头指针,对表尾进行操作需要O(n)的时间复杂度,而设的是尾指针r,r->next 即是头指针,对表头和表尾进行操作都只需要O(1)的时间复杂度。

 

1.2 基本操作

//初始化
//求表长
//判空
//整表创建 尾插法
//遍历输入
//整表清除
//整表创建 头插法
//插入
//按位查找
//按值查找
//删除

1.3 代码实现

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <stdlib.h>

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0


typedef int ElemType;
typedef int Status;

typedef struct Node
{
	ElemType data;
	struct Node* next;
}Node,*LinkList;

1.3.1 初始化

//初始化循环单链表
Status InitList(LinkList* L)
{
	//开辟内存空间
	*L = (LinkList)malloc(sizeof(Node));  //创建头结点,并让头指针L指向此结点
	if (!(*L))
	{
		return ERROR;
	}
	//头指针的指针域 指向 头结点   //循环
	(*L)->next = (*L);
	
}


1.3.2 求表长

/* 初始条件:循环单链表L已存在。操作结果:返回L中数据元素个数 */
int ListLength(LinkList L)
{
	LinkList p = L;   //指针p指向头结点
	int i = 0;
	while (p->next != L)    //当指针p的下一个结点不是头结点时进入循环
	{
		p = p->next;    //p指向下一个结点
		i++;
	}

	return i;
}


1.3.3 判空

/* 初始条件:链式线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
Status ListEmpty(LinkList L)
{
	if (L->next == L)   //若头结点的指针域 指向 它自己,则为空
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

        

1.3.4 整表创建 头插法

 

/*  随机产生n个元素的值,建立带表头结点的循环单链表L(头插法) */
void CreateList_Head(LinkList* L, int n)
{
	//srand(time(0));   //初始化随机种子

	//创建一个带头结点的单链表
	(*L) = (LinkList)malloc(sizeof(Node));
	(*L)->next = (*L);

	//在头结点后,循环插入n个随机数
	LinkList p;
	for (int i = 0; i < n; i++)
	{
		//创建新的结点,并让p指向新的结点
		p = (LinkList)malloc(sizeof(Node));
		p->data = i;
		//p->data = rand() % 100 + 1;  //随机生成100以内的数字

		p->next = (*L)->next;   //把头结点后面的结点(第一个结点)的地址 赋值 给新指针p指向结点的指针域
		(*L)->next = p;
	}
}


1.3.5 遍历输入

/* 初始条件:循环单链表L已存在 */
/* 操作结果:依次对L的每个数据元素输出 */
Status visit(ElemType c)
{
	printf("%d ", c);
	return OK;
}

void ListTraverse(LinkList L)
{
	LinkList p = L->next;   //指针p指向第一个结点
	while (p != L)  //当遍历到最后一个结点后,循环单链表回到头结点,遍历结束
	{
		visit(p->data);
		p = p->next;    //指针p指向下一个结点
	}
	printf("\n");
	return OK;
}

        测试代码:

1.3.6 整表清除

/* 初始条件:循环单链表L已存在。操作结果:将L重置为空表 */
Status ListClear(LinkList* L)
{
	LinkList p, q;
	//指针p指向第一个结点
	p = (*L)->next;

	while (p != *L)
	{
		q = p->next;  //指针q指向 p指向结点的 后一个结点(把p指向结点 后一个结点的地址赋值给q)
		free(p);   //释放 p指向的结点
		p = q;     //让指针p指向(新的)第一个结点
	}

	(*L)->next = (*L);   //头结点的指针域 指向头结点
	return OK;
}

        测试代码:

1.3.7 整表创建 头插法

/*  随机产生n个元素的值,建立带表头结点的循环单链表L(尾插法) */
void CreateList_Tail(LinkList* L, int n)
{
	//srand(time(0));   //初始化随机种子

	(*L) = (LinkList)malloc(sizeof(Node));   //创建头结点

	LinkList p, r;  //声明两个结构体指针
	r = (*L);    //指针r 指向链表尾部的结点

	for (int i = 0; i < n; i++)
	{
		p = (Node*)malloc(sizeof(Node));  //创建新结点,让p指向新结点
		//p->data = rand() % 100 + 1;
		p->data = i;

		r->next = p;   //把新结点的地址 赋值给 表尾结点的指针域 
		r = p;        //让r指向新的表尾结点
	}

	r->next = (*L);
}

        测试代码:

1.3.8 插入


/* 初始条件:循环单链表L已存在,1≤i≤ListLength(L), */
/* 操作结果:在L中第i个位置之前插入新的数据元素e*/
Status ListInsert(LinkList* L, int i, ElemType e)
{
	LinkList p, s;
	p = (*L); //p指向头结点
	int j = 1;
	while ((p->next != (*L)) && j < i)   //逻辑与,同真才为真,即需要同时满足两个条件才进入循环
	{
		p = p->next;
		j++;
	}
	if ((p->next == L) || j > i)   
	{
		return ERROR;
	}

	s = (LinkList)malloc(sizeof(Node));
	s->data = e;
	s->next = p->next;    //把p的后继结点的地址 赋值给 s的指针域
	p->next = s;    //再把s的地址 赋值给 p的指针域

	return OK;
}

        测试代码:

1.3.9 按位查找

/* 初始条件:L已存在,1≤i≤ListLength(L) */
/* 操作结果:用e返回L中第i个数据元素的值 */
//按位查找
Status GetElem(LinkList L, int i, ElemType* e)
{
	LinkList p;
	p = L->next;    //指针p指向第一个结点
	int j = 1;             //当查找的元素i为1时,直接返回p指向结点的数据域
	while ((p->next != L) && j < i)   //逻辑与,同真才为真,同时满足两个条件才进入循环
	{
		p = p->next;    //让p指向下一个结点
		j++;
	}
	if (j > i)   //逻辑与,同假为假,即满足其中一个条件,便可进入循环
	{
		return ERROR;
	}
	*e = p->data;

	return OK;
}

1.3.10 按值查找

/* 初始条件:循环单链表L已存在 */
/* 操作结果:返回L中第1个与e满足关系的数据元素的位序。 */
/* 若这样的数据元素不存在,则返回值为0 */
Status LocateElem(LinkList L, ElemType e)
{
	LinkList p = L->next;  //p指向头结点的后继结点(第一个结点)
	int i = 1;
	while (p != L)
	{
		if (p->data == e)
		{
			return i;
		}
		else
		{
			p = p->next;
			i++;
		}
	}

	return 0;
}


1.3.11 删除

 

/* 初始条件:循环单链表L已存在,1≤i≤ListLength(L) */
/* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */
Status ListDelete(LinkList* L, int i, ElemType* e)
{
	LinkList p, q;
	p = (*L);  // p指向头结点
	int j = 1;
	while ((p->next != L) && j < i)
	{
		p = p->next;
		j++;
	}
	if ((p->next == L) || j > i)
	{
		return ERROR;
	}
	q = p->next;
	p->next = q->next;
	*e = q->data;
	free(q);

	return OK;
}

 

 1.4 完整代码

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <stdlib.h>

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0


typedef int ElemType;
typedef int Status;

typedef struct Node
{
	ElemType data;
	struct Node* next;
}Node,*LinkList;


//初始化循环单链表
Status InitList(LinkList* L)
{
	//开辟内存空间
	*L = (LinkList)malloc(sizeof(Node));  //创建头结点,并让头指针L指向此结点
	if (!(*L))
	{
		return ERROR;
	}
	//头指针的指针域 指向 头结点   //循环
	(*L)->next = (*L);
	
}


/* 初始条件:链式线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
Status ListEmpty(LinkList L)
{
	if (L->next == L)   //若头结点的指针域 指向 它自己,则为空
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}


/* 初始条件:循环单链表L已存在。操作结果:返回L中数据元素个数 */
int ListLength(LinkList L)
{
	LinkList p = L;   //指针p指向头结点
	int i = 0;
	while (p->next != L)    //当指针p的下一个结点不是头结点时进入循环
	{
		p = p->next;    //p指向下一个结点
		i++;
	}

	return i;
}

/*  随机产生n个元素的值,建立带表头结点的循环单链表L(头插法) */
void CreateList_Head(LinkList* L, int n)
{
	//srand(time(0));   //初始化随机种子

	//创建一个带头结点的单链表
	(*L) = (LinkList)malloc(sizeof(Node));
	(*L)->next = (*L);

	//在头结点后,循环插入n个随机数
	LinkList p;
	for (int i = 0; i < n; i++)
	{
		//创建新的结点,并让p指向新的结点
		p = (LinkList)malloc(sizeof(Node));
		p->data = i;
		//p->data = rand() % 100 + 1;  //随机生成100以内的数字

		p->next = (*L)->next;   //把头结点后面的结点(第一个结点)的地址 赋值 给新指针p指向结点的指针域
		(*L)->next = p;
	}
}

/* 初始条件:循环单链表L已存在 */
/* 操作结果:依次对L的每个数据元素输出 */
Status visit(ElemType c)
{
	printf("%d ", c);
	return OK;
}

void ListTraverse(LinkList L)
{
	LinkList p = L->next;   //指针p指向第一个结点
	while (p != L)  //当遍历到最后一个结点后,循环单链表回到头结点,遍历结束
	{
		visit(p->data);
		p = p->next;    //指针p指向下一个结点
	}
	printf("\n");
	return OK;
}



/* 初始条件:循环单链表L已存在。操作结果:将L重置为空表 */
Status ListClear(LinkList* L)
{
	LinkList p, q;
	//指针p指向第一个结点
	p = (*L)->next;

	while (p != *L)
	{
		q = p->next;  //指针q指向 p指向结点的 后一个结点(把p指向结点 后一个结点的地址赋值给q)
		free(p);   //释放 p指向的结点
		p = q;     //让指针p指向(新的)第一个结点
	}

	(*L)->next = (*L);   //头结点的指针域 指向头结点
	return OK;
}

/*  随机产生n个元素的值,建立带表头结点的循环单链表L(尾插法) */
void CreateList_Tail(LinkList* L, int n)
{
	//srand(time(0));   //初始化随机种子

	(*L) = (LinkList)malloc(sizeof(Node));   //创建头结点

	LinkList p, r;  //声明两个结构体指针
	r = (*L);    //指针r 指向链表尾部的结点

	for (int i = 0; i < n; i++)
	{
		p = (Node*)malloc(sizeof(Node));  //创建新结点,让p指向新结点
		//p->data = rand() % 100 + 1;
		p->data = i;

		r->next = p;   //把新结点的地址 赋值给 表尾结点的指针域 
		r = p;        //让r指向新的表尾结点
	}

	r->next = (*L);
}

/* 初始条件:循环单链表L已存在,1≤i≤ListLength(L), */
/* 操作结果:在L中第i个位置之前插入新的数据元素e*/
Status ListInsert(LinkList* L, int i, ElemType e)
{
	LinkList p, s;
	p = (*L); //p指向头结点
	int j = 1;
	while ((p->next != (*L)) && j < i)   //逻辑与,同真才为真,即需要同时满足两个条件才进入循环
	{
		p = p->next;
		j++;
	}
	if ((p->next == L) || j > i)   
	{
		return ERROR;
	}

	s = (LinkList)malloc(sizeof(Node));
	s->data = e;
	s->next = p->next;    //把p的后继结点的地址 赋值给 s的指针域
	p->next = s;    //再把s的地址 赋值给 p的指针域

	return OK;
}

/* 初始条件:L已存在,1≤i≤ListLength(L) */
/* 操作结果:用e返回L中第i个数据元素的值 */
//按位查找
Status GetElem(LinkList L, int i, ElemType* e)
{
	LinkList p;
	p = L->next;    //指针p指向第一个结点
	int j = 1;             //当查找的元素i为1时,直接返回p指向结点的数据域
	while ((p->next != L) && j < i)   //逻辑与,同真才为真,同时满足两个条件才进入循环
	{
		p = p->next;    //让p指向下一个结点
		j++;
	}
	if (j > i)   //逻辑与,同假为假,即满足其中一个条件,便可进入循环
	{
		return ERROR;
	}
	*e = p->data;

	return OK;
}

/* 初始条件:循环单链表L已存在 */
/* 操作结果:返回L中第1个与e满足关系的数据元素的位序。 */
/* 若这样的数据元素不存在,则返回值为0 */
Status LocateElem(LinkList L, ElemType e)
{
	LinkList p = L->next;  //p指向头结点的后继结点(第一个结点)
	int i = 1;
	while (p != L)
	{
		if (p->data == e)
		{
			return i;
		}
		else
		{
			p = p->next;
			i++;
		}
	}

	return 0;
}


/* 初始条件:循环单链表L已存在,1≤i≤ListLength(L) */
/* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */
Status ListDelete(LinkList* L, int i, ElemType* e)
{
	LinkList p, q;
	p = (*L);  // p指向头结点
	int j = 1;
	while ((p->next != L) && j < i)
	{
		p = p->next;
		j++;
	}
	if ((p->next == L) || j > i)
	{
		return ERROR;
	}
	q = p->next;
	p->next = q->next;
	*e = q->data;
	free(q);

	return OK;
}

void test01()
{
	LinkList L;
	//初始化
	InitList(&L);
	//判空
	Status i_empty = ListEmpty(L);
	printf("表是否为空(1为是/0为否):%d\n", i_empty);   //表是否为空(1为是/0为否):1
	//求表长
	int i_length = ListLength(L);
	printf("表的长度为:%d\n", i_length);  //表的长度为:0
}


void test02()
{
	LinkList L;
	//头插法
	CreateList_Head(&L,10);  //在表头插入0~9
	//判空
	Status i_empty = ListEmpty(L);
	printf("表是否为空(1为是/0为否):%d\n", i_empty);  //表是否为空(1为是/0为否):0
	//求表长
	int i_length = ListLength(L);
	printf("表的长度为:%d\n", i_length);    //表的长度为:10
	//遍历
	ListTraverse(L);  //9 8 7 6 5 4 3 2 1 0

	printf("---------------------------------------\n");

	//清空表
	ListClear(&L);
	//判空
	i_empty = ListEmpty(L);
	printf("表是否为空(1为是/0为否):%d\n", i_empty);  //表是否为空(1为是/0为否):1
	//求表长
	i_length = ListLength(L);
	printf("表的长度为:%d\n", i_length);    //表的长度为:0
	//遍历
	ListTraverse(L);  //(为空)



}


void test03()
{
	LinkList L;
	//创建循环单链表(尾插法)
	CreateList_Tail(&L, 10);
	//判空
	Status i_empty = ListEmpty(L);
	printf("表是否为空(1为是/0为否):%d\n", i_empty);  //表是否为空(1为是/0为否):0
	//求表长
	int i_length = ListLength(L);
	printf("表的长度为:%d\n", i_length);    //表的长度为:10
	//遍历
	ListTraverse(L);  //0 1 2 3 4 5 6 7 8 9

	printf("-----------------------------------\n");

	ListInsert(&L, 10, 20); //在表中第10个位置之前插入20
	//判空
	i_empty = ListEmpty(L);
	printf("表是否为空(1为是/0为否):%d\n", i_empty);  //表是否为空(1为是/0为否):0
	//求表长
	i_length = ListLength(L);
	printf("表的长度为:%d\n", i_length);    //表的长度为:11
	//遍历
	ListTraverse(L);   //0 1 2 3 4 5 6 7 8 20 9

	printf("-----------------------------------\n");
	//按位查找
	//int i = 11;
	//ElemType e ;
	//GetElem(L, i, &e);
	//printf("表中第 %d 位元素为 %d \n", i, e);  //表中第 1 位元素为 0


	//按值查找
	//ElemType e = 9;
	//Status i_locate = LocateElem(L, e);
	//printf("元素 %d 位于标志的第 %d 位(0表示元素不存在)\n", e, i_locate);  //元素 9 位于标志的第 11 位(0表示元素不存在)

	//按位删除
	ElemType e = 0;
	int i = 10;
	ListDelete(&L, i, &e);
	printf("表中被删除的位序为%d的元素是 %d \n", i, e);   //表中被删除的位序为10的元素是 20
}

int main()
{
	test01();

	//test02();

	//test03();

	system("pause");
	return 0;
}

2.循环双向链表 

2.1 定义

      由循环单链表的定义不难推出循环双链表。不同的是在循环双链表中,头结点的prior指针还要指向表尾结点。

 

 

2.2 基本操作

//初始化
//求表长
//判空
//整表创建 尾插法
//遍历
//整表清空
//插入
//按位查找
//按值查找
//删除

2.3 代码实现

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <stdlib.h>


#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

typedef int Status;
typedef int ElemType;

typedef struct DLNode
{
	ElemType data;
	struct DLNode* prior;
	struct DLNode* next;
}DLNode,*DLinkList;

2.3.1 初始化


//初始化循环双向链表
Status InitList(DLinkList* DL)
{
	//动态开辟一个结点的空间
	(*DL) = (DLinkList)malloc(sizeof(DLNode));  //创建头结点 并让头指针DL指向该结点

	if (!(*DL)) //开辟空间失败,返回FALSE
	{
		return ERROR;
	}

	(*DL)->prior = (*DL);   //将头结点的 前继指针和后继指针指向其自己
	(*DL)->next = (*DL);

	return OK;
}


2.3.2 求表长

//求表长
int ListLength(DLinkList DL)
{
	DLinkList p = DL->next;
	int i = 0;
	while(p != DL)
	{
		p = p->next;
		i++;
	}
	return i;
}


2.3.3 判空

//判空(空返回TRUE,不为空返回FALSE)
Status ListEmpty(DLinkList DL)
{
	if (DL->next != DL) 
	{
		return FALSE;  //不为空
	}
	else
	{ 
		return TRUE;  //为空
	}
}


2.3.4 整表创建 尾插法

//整表创建
//创建一个n个元素的双向循环链表
void CreateList_Tail(DLinkList* DL, int n)
{
	//初始化
	(*DL) = (DLinkList)malloc(sizeof(DLNode));
	(*DL)->prior = (*DL);
	(*DL)->next = (*DL);

	DLinkList p, s;
	p = (*DL);
	for (int i = 0; i < n; i++)
	{
		//创建新的结点
		s = (DLinkList)malloc(sizeof(DLNode));
		s->data = i;

		s->prior = p;
		s->next = p->next;
		p->next = s;
		(*DL)->prior = s;

		p = s; //p指针向后移动到新的结点
		//printf("%d ", p->data);
	}

}


2.3.5 遍历

//遍历输出
/* 初始条件:双向循环链表DL已存在 */
/* 操作结果:依次对DL的每个数据元素输出 */
Status visit(ElemType c)
{
	printf("%d ", c);
	return OK;
}

void ListTraverse(DLinkList DL)
{
	DLinkList p = DL->next;
	while (p != DL)
	{
		//visit(p->data);
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");

}

 


2.3.6 整表清空

//清空表
Status ListClear(DLinkList* DL)
{
	DLinkList p, q;
	p = (*DL)->next;

	while (p != (*DL))
	{
		q = p->next;
		free(p);
		p = q;
	}
	(*DL)->next = (*DL);
}

 


2.3.7 插入

//按位插入(1 <= i <= length)
Status ListInsert(DLinkList* DL, int i, ElemType e)
{
	DLinkList p, s;
	p = (*DL); // p指向头结点
	int j = 1;
	while (p->next != (*DL) && j < i)
	{
		p = p->next;
		j++;
	}
	if (p->next == (*DL) || j > i)  //空表 或 输入非法时
	{
		return ERROR;
	}

	s = (DLinkList)malloc(sizeof(DLNode));
	s->data = e;

	s->prior = p;
	s->next = p->next;
	p->next->prior = s;
	p->next = s;

	p = s;

	return OK;
}


2.3.8 按位查找

 

//按位查找
Status GetElem(DLinkList DL, int i, ElemType* e)
{
	DLinkList p = DL->next;   //p指向第一个结点
	int j = 1;
	while ((p != DL) && j < i)   //p不指向头结点 与 j<i 同时满足时进入循环
	{
		p = p->next;               //向后遍历寻找第i个元素
		j++;
	}
	if ((p == DL) || j > i)     // 为空表 或 输入i值非法  有一个被满足时进入分支
	{
		return ERROR;         
	}
	
	*e = p->data;

	return OK;
}


2.3.9 按值查找

 

//按值查找
Status LocateElem(DLinkList DL, ElemType e)
{
	DLinkList p = (DL)->next;

	int i = 1;
	while (p != DL)
	{
		if (p->data == e)
		{
			return i;
		}
		else
		{
			p = p->next;
			i++;
		}
	}

	return FALSE;
}


2.3.10 删除

 


//按位删除
Status DeleteElem(DLinkList* DL, int i, ElemType* e)
{
	DLinkList p = (*DL)->next;
	int j = 1;
	while ((p != (*DL)) && j < i)
	{
		p = p->next;
		j++;
	}
	if ((p == (*DL)) || j > i)
	{
		return ERROR;
	}

	*e = p->data;
	
	p->prior->next = p->next;
	p->next->prior = p->prior;
	free(p);
	
	return OK;
}

2.4 双向循环链表的完整代码实现

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <stdlib.h>


#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

typedef int Status;
typedef int ElemType;

typedef struct DLNode
{
	ElemType data;
	struct DLNode* prior;
	struct DLNode* next;
}DLNode,*DLinkList;

//初始化双向循环链表
Status InitList(DLinkList* DL)
{
	//动态开辟一个结点的空间
	(*DL) = (DLinkList)malloc(sizeof(DLNode));  //创建头结点 并让头指针DL指向该结点

	if (!(*DL)) //开辟空间失败,返回FALSE
	{
		return ERROR;
	}

	(*DL)->prior = (*DL);   //将头结点的 前继指针和后继指针指向其自己
	(*DL)->next = (*DL);

	return OK;
}

//求表长
int ListLength(DLinkList DL)
{
	DLinkList p = DL->next;
	int i = 0;
	while(p != DL)
	{
		p = p->next;
		i++;
	}
	return i;
}

//判空(空返回TRUE,不为空返回FALSE)
Status ListEmpty(DLinkList DL)
{
	if (DL->next != DL) 
	{
		return FALSE;  //不为空
	}
	else
	{ 
		return TRUE;  //为空
	}
}

//整表创建
//创建一个n个元素的双向循环链表
void CreateList_Tail(DLinkList* DL, int n)
{
	//初始化
	(*DL) = (DLinkList)malloc(sizeof(DLNode));
	(*DL)->prior = (*DL);
	(*DL)->next = (*DL);

	DLinkList p, s;
	p = (*DL);
	for (int i = 0; i < n; i++)
	{
		//创建新的结点
		s = (DLinkList)malloc(sizeof(DLNode));
		s->data = i;

		s->prior = p;
		s->next = p->next;
		p->next = s;
		(*DL)->prior = s;

		p = s; //p指针向后移动到新的结点
		//printf("%d ", p->data);
	}

}

//遍历输出
/* 初始条件:双向循环链表DL已存在 */
/* 操作结果:依次对DL的每个数据元素输出 */
Status visit(ElemType c)
{
	printf("%d ", c);
	return OK;
}

void ListTraverse(DLinkList DL)
{
	DLinkList p = DL->next;
	while (p != DL)
	{
		//visit(p->data);
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");

}


//清空表
Status ListClear(DLinkList* DL)
{
	DLinkList p, q;
	p = (*DL)->next;

	while (p != (*DL))
	{
		q = p->next;
		free(p);
		p = q;
	}
	(*DL)->next = (*DL);
}

//按位插入(1 <= i <= length)
Status ListInsert(DLinkList* DL, int i, ElemType e)
{
	DLinkList p, s;
	p = (*DL); // p指向头结点
	int j = 1;
	while (p->next != (*DL) && j < i)
	{
		p = p->next;
		j++;
	}
	if (p->next == (*DL) || j > i)  //空表 或 输入非法时
	{
		return ERROR;
	}

	s = (DLinkList)malloc(sizeof(DLNode));
	s->data = e;

	s->prior = p;
	s->next = p->next;
	p->next->prior = s;
	p->next = s;

	p = s;

	return OK;
}

//按位查找
Status GetElem(DLinkList DL, int i, ElemType* e)
{
	DLinkList p = DL->next;   //p指向第一个结点
	int j = 1;
	while ((p != DL) && j < i)   //p不指向头结点 与 j<i 同时满足时进入循环
	{
		p = p->next;               //向后遍历寻找第i个元素
		j++;
	}
	if ((p == DL) || j > i)     // 为空表 或 输入i值非法  有一个被满足时进入分支
	{
		return ERROR;         
	}
	
	*e = p->data;

	return OK;
}


//按值查找
Status LocateElem(DLinkList DL, ElemType e)
{
	DLinkList p = (DL)->next;

	int i = 1;
	while (p != DL)
	{
		if (p->data == e)
		{
			return i;
		}
		else
		{
			p = p->next;
			i++;
		}
	}

	return FALSE;
}

//按位删除
Status DeleteElem(DLinkList* DL, int i, ElemType* e)
{
	DLinkList p = (*DL)->next;
	int j = 1;
	while ((p != (*DL)) && j < i)
	{
		p = p->next;
		j++;
	}
	if ((p == (*DL)) || j > i)
	{
		return ERROR;
	}

	*e = p->data;
	
	p->prior->next = p->next;
	p->next->prior = p->prior;
	free(p);
	
	return OK;
}

void test01()
{
	//整表创建 尾插法
	DLinkList DL;
	CreateList_Tail(&DL, 10);
	//判空
	Status i_empty = ListEmpty(DL);
	printf("表是否为空(1为是/0为否):%d\n", i_empty);  //表是否为空(1为是/0为否):0
	//求表长
	int i_length = ListLength(DL);
	printf("表的长度为:%d\n", i_length);  //	表的长度为:10
	//遍历
	ListTraverse(DL);  //0 1 2 3 4 5 6 7 8 9

	printf("--------------------------------------\n");
	
	清空表
	//ListClear(&DL);
	判空
	//i_empty = ListEmpty(DL);
	//printf("表是否为空(1为是/0为否):%d\n", i_empty);  // 表是否为空(1为是/0为否):1
	求表长
	//i_length = ListLength(DL);
	//printf("表的长度为:%d\n", i_length);  //	表的长度为:0
	遍历
	//ListTraverse(DL);  //

	printf("--------------------------------------\n");

	//按位插入
	ListInsert(&DL, 1, 10);  //在表中第1个元素之前插入10
	//判空
	i_empty = ListEmpty(DL);
	printf("表是否为空(1为是/0为否):%d\n", i_empty);  //表是否为空(1为是/0为否):0
	//求表长
	i_length = ListLength(DL);
	printf("表的长度为:%d\n", i_length);  //	表的长度为:11
	//遍历
	ListTraverse(DL);  //	10 0 1 2 3 4 5 6 7 8 9

	printf("--------------------------------------\n");

	//按位查找
	ElemType e1 = 0;
	int i1 = 1;
	GetElem(DL, i1, &e1);
	printf("表中第 %d 个元素是 %d \n", i1, e1);  //表中第 1 个元素是 10

	//按值查找
	ElemType e2 = 10;
	int i2 = LocateElem(DL,e2);
	printf("值为 %d 的元素在表的第 %d 个位置\n", e2, i2);   //值为 10 的元素在表的第 1 个位置

	//按位删除
	int i3 = 11;
	ElemType e3 = -1;
	DeleteElem(&DL, i3, &e3);
	printf("表中被删除的第 %d 个元素为 %d \n", i3, e3);  //表中被删除的第 11 个元素为 9
	//求表长
	i_length = ListLength(DL);
	printf("表的长度为:%d\n", i_length);  //	表的长度为:10
	//遍历
	ListTraverse(DL);  //10 0 1 2 3 4 5 6 7 8
}

void test02()
{
	DLinkList DL;
	//初始化
	InitList(&DL);
	//判空
	Status i_empty = ListEmpty(DL);
	printf("表是否为空(1为是/0为否):%d\n", i_empty);  //表是否为空(1为是/0为否):1
	//求表长
	int i_length = ListLength(DL);
	printf("表的长度为:%d\n", i_length);  // 表的长度为:0

}

int main()
{

	//test01();

	test02();

	system("pause");
	return 0;
}

 END

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值