目录
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;
}
![](https://img-blog.csdnimg.cn/290a04a51c1c4d18936f553af2de00c1.png)
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;
}
![](https://img-blog.csdnimg.cn/37f77b56cfb74c8bba56133615096a73.png)
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;
}
![](https://img-blog.csdnimg.cn/f30ee73986db482d86beaeb137ca2e01.png)
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