c语言一维数组单循环,数据结构与算法-C语言8-单循环列表

数据结构与算法-目录

循环链表是另一种形式的链式存贮结构。它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环。

e36b605024e6

对于单个链表,由于每个结点只存储了向后的指针,到了尾标志就停止了向后链的操作,这样当中某一结点就无法找到它的前驱结点了。

将单链表中终端结点的指针由空指针改为指向头结点,就使整个单链表形成一个环, 这种头尾相接的单链表称为单循环链表,简称循环链表。

循环链表解决了一个很麻烦的问题,如何从当中一个结点出发,访问到链表的全部结点。

循环链表和单链表的主要差异就是在于循环的判断条件上,原来是判断p->next是否为空,现在则是p->next不等于头结点,则循环未结束。

示例程序

CList.h

//CList.h

//结构体定义以及函数声明

#ifndef CLIST_H

#define CLIST_H

#include

#include

#include

#include

typedef int ElemType;

typedef struct Node

{

ElemType data;

struct Node *next;

}Node, *PNode;

typedef struct List

{

PNode head;

PNode tail;

int size;

}List,*PList;

bool InitList(PList list);

void Create_t(PList list,ElemType x); //尾插

void Create_h(PList list,ElemType x); //头插

void del_back(PList list); //尾删

void del_front(PList list); //头删

void sortList(PList list); //排序

void insert_val(PList list,ElemType x); //按值插

PNode find(PList list,ElemType x);

void del_val(PList list,ElemType x);

void modify(PList list,ElemType x1,ElemType x2);

void clear(PList list);

void destroy(PList list);

void reserve(PList list);

int length(PList list);

void menu();

void showList(PList list);

void show_tail(PList list);

ElemType next(PList list,ElemType x);

ElemType prio(PList list,ElemType x);

PNode prev(PList list,PNode p);

#endif

CList.cpp

//CList.cpp

//函数实现

#include"CList.h"

void menu() //提供选项的菜单函数

{

printf("***************************************************************\n");

printf("* [0] quit_system [1] Create_t [2] Create_h [3] showList *\n");

printf("* [4] del_back [5] del_front [6] insert_val [7] show_tail*\n");

printf("* [8] find [9] del_val [10] sortList [11] modify *\n");

printf("* [12]clear [13]destroy [14] resver [15]length *\n");

printf("* [16] next [17]prio *\n");

printf("***************************************************************\n");

}

bool InitList(PList list)

{

list->head = (PNode)malloc(sizeof(Node)); //初始化一个头结点

assert(list->head != NULL); //断言,表达式为真,接着往下执行

list->head->next = list->head; //初始化head和tail指针,使其都指向头节点

list->tail = list->head;

list->size = 0; //长度初始化为0

return true;

}

void Create_t(PList list,ElemType x) //尾插法

{

PNode s = (PNode)malloc(sizeof(Node));

assert(s != NULL);

s->data = x; //填充数据域

list->tail->next = s; //tail指向最后一个节点,把新建立的节点链接到链表的最后

s->next = list->head; //单循环链表,新节点的next指向头结点

list->tail = s; //改变尾指针的指向

list->size++;

}

void showList(PList list) //链表显示函数

{

if(1>list->size)

{

printf("--链表为空\n");

return ;

}

PNode p = list->head->next;

while(list->head != p) //逐个遍历链表

{

printf("%d ",p->data);

p=p->next;

}

printf("\n");

}

void Create_h(PList list,ElemType x) //头插法

{

PNode s = (PNode)malloc(sizeof(Node));

assert(s != NULL);

s->data = x; //填充数据域

s->next = list->head->next; //新节点指向第一个节点

list->head->next = s; //头节点的next指向新节点s

if(list->size == 0) //如果是第一次头插,需改变尾指针和尾节点的next指向,之后都不改变

{

list->tail = s;

list->tail->next = list->head;

}

list->size++; //插入一个,长度加1

}

void del_back(PList list) //尾删

{

if(0==list->size)

return;

PNode p = list->head;

while(list->head != p->next->next) //找到倒数第二个节点

{

p = p->next;

}

p->next = list->head; //把最后一个节点分离

free(list->tail); //释放最后一个节点

list->tail = p; //尾指针指向原来的倒数第二个节点(现在倒数第一)

printf("--尾节点已删除\n");

list->size--;

}

void del_front(PList list) //头删

{

if(0==list->size)

return;

else

{

PNode p = list->head->next;

if(1==list->size)

{ //只有一个节点,若删去,需改变尾指针

list->tail = list->head;

list->head->next = list->head;

}

else

{

list->head->next = p->next; //头指针指向第二个节点

}

free(p); //释放第一个节点

}

printf("--头节点已删除\n");

list->size--;

}

void show_tail(PList list) //为测试尾指针是否正确改变,需显示最后一个节点

{

printf("--链表的尾节点是:》%d \n",list->tail->data);

}

void sortList(PList list) // 对无序链表进行从小到大排序

{

if(2>list->size)

return ;

PNode p = list->head->next;

PNode q = p->next;

for(int i = 0;isize-1;i++,p = list->head->next,q = p->next) //n个数比较n-1趟

{

for(int j = 0;jsize-1-i;j++,p=q,q=q->next) //第i趟比较n-i次

{

if(p->data > q->data) //如果前面的数大于后面,则交换

{

p->data = p->data + q->data;

q->data = p->data - q->data;

p->data = p->data - q->data;

}

}

}

}

void insert_val(PList list,ElemType x) //链表有序的前提下,给一个值插入

{

PNode p = list->head->next,q = list->head;

while(list->head != p) //找到能插入的位置,会在p、q之间

{

if(xdata)

break;

q = p;

p = p->next;

}

PNode s = (PNode)malloc(sizeof(Node)); //初始化新节点

s->data = x;

q->next = s; //把新节点插入到链表中(在p,q之间插入)

s->next = p;

if(list->head == p) //如果新节点的值最大,即尾插,需改变尾指针和尾节点的next指向

{

list->tail = s;

list->tail->next=list->head;

}

list->size++;

}

PNode find(PList list,ElemType x) //返回要查找元素的前面一个的地址

{

PNode p = list->head;

while(list->tail != p && list->head != p->next && x != p->next->data)

{

p = p->next; //循环结束,p指向x的前面一个元素

}

if(list->head == p->next) //如果p指向最后一个元素,说明没有找到

{

printf("--没找到!\n");

return NULL;

}

return p;

}

void del_val(PList list,ElemType x) //删除指定的值x

{

if(0 == list->size)

return ;

PNode p = find(list,x);

PNode q = NULL;

if(NULL != p)

{

q = p->next; //q指向要删除的节点

if(q == list->tail) //若删除最后一个节点,需改变尾指针

{

p->next = list->head;

list->tail = p;

}

else

{

p->next = q->next;

}

free(q); //释放要删除的节点

list->size--;

printf("--%d已删除!\n",x);

}

return ;

}

void modify(PList list,ElemType x1,ElemType x2) //把原有的x1修改成x2

{

PNode p = find(list,x1);

if(NULL != p)

p->next->data = x2;

else

return ;

}

void clear(PList list) //删除链表的所有节点,但不删除头结点

{

PNode p = list->head->next;

PNode q = p;

while(list->head != p)

{

p = p->next; //p依次后移,跟屁虫q依次释放节点

free(q);

q = p;

}

list->tail = list->head; //修改尾指针和链表长度

list->head->next = list->head;

list->size = 0;

printf("--链表已被清空!\n");

}

void destroy(PList list) //摧毁链表,包括所有节点和头结点

{

clear(list);

free(list->head);

list->head = NULL;

list->tail = NULL;

printf("--链表已被摧毁!\n");

}

PNode prev(PList list,PNode p) //返回p指向的前面一个节点

{

if(p != list->head)

{

PNode q = list->head->next;

while(q != list->head && q->next != p) //依次往后移,知道尾指针的前面一个节点

q=q->next;

if(q->next == p)

return q;

}

return NULL;

}

void reserve(PList list) //逆置链表

{

PNode s = (PNode)malloc(sizeof(Node)); //建立一个节点

s->next = list->tail;

PNode p = list->tail;

while(list->tail != list->head->next) //把原链表的尾节点到第一个节点依次连接到新节点上

{

list->tail = prev(list,list->tail);

list->tail->next = list->head;

p->next = list->tail;

p=p->next;

}

p->next = s; //p指向第一个节点,即新链表的最后一个节点,尾指针的next指向头结点s,链表结束

free(list->head); //释放原来的头结点

list->head = s; //把s变成新的头指针

}

int length(PList list) //求链表的长度

{

return list->size;

}

ElemType next(PList list,ElemType x) //返回x的后继

{

PNode p = find(list,x);

if(NULL == p)

return -1;

if(p->next == list->tail) //因为是单循环链表,尾节点的下一个元素是第一个节点

{

return list->head->next->data;

}

p=p->next;

return p->next->data;

}

ElemType prio(PList list,ElemType x) //返回x的前驱

{

PNode p = find(list,x);

if(NULL != p)

{

if(p == list->head || p == list->tail)

{

return list->tail->data;

}

return p->data;

}

return -1;

}

main.cpp

//main.cpp

//测试函数

#include "CList.h"

int main()

{

List mylist;

InitList(&mylist);

ElemType item = 0;

int pos = 0;

int chose = 1;

PNode p = NULL;

while(chose)

{

menu();

printf("给出想要操作的序号:\n");

scanf("%d",&chose);

switch(chose)

{

case 0:

destroy(&mylist);

chose = 0;

break;

case 1:

printf("输入要尾插的数据[-1结束]:\n");

while(scanf("%d",&item),item!=-1)

{

Create_t(&mylist,item);

}

break;

case 2:

printf("输入要头插的数据:\n");

while(scanf("%d",&item),item!=-1)

{

Create_h(&mylist,item);

}

break;

case 3:

showList(&mylist);

break;

case 4:

del_back(&mylist);

break;

case 5:

del_front(&mylist);

break;

case 6:

printf("给出要插入的数:\n");

scanf("%d",&item);

insert_val(&mylist,item);

break;

case 7:

show_tail(&mylist);

break;

case 8:

printf("输入要查找的数:\n");

scanf("%d",&item);

p = find(&mylist,item);

if(NULL!=p)

printf("%d\n",p->next->data);

break;

case 9:

printf("输入要删除的数:\n");

scanf("%d",&item);

del_val(&mylist,item);

break;

case 10:

sortList(&mylist);

break;

case 11:

printf("输入要修改的数和修改后的数\n");

scanf("%d %d",&item,&pos);

modify(&mylist,item,pos);

break;

case 12:

clear(&mylist);

break;

case 13:

destroy(&mylist);

break;

case 14:

reserve(&mylist);

break;

case 15:

printf("链表长度为:%d\n",length(&mylist));

break;

case 16:

printf("输入想要找哪个一数的后继:\n");

scanf("%d",&item);

printf("%d 的后继是:%d\n",item,next(&mylist,item));

break;

case 17:

printf("输入想要找哪个一数的前驱:\n");

scanf("%d",&item);

printf("%d 的前驱是:%d\n",item,prio(&mylist,item));

break;

default:

printf("重新输入\n");

break;

}

}

return 0;

}

运行测试:

***************************************************************

* [0] quit_system [1] Create_t [2] Create_h [3] showList *

* [4] del_back [5] del_front [6] insert_val [7] show_tail*

* [8] find [9] del_val [10] sortList [11] modify *

* [12]clear [13]destroy [14] resver [15]length *

* [16] next [17]prio *

***************************************************************

给出想要操作的序号:

1

输入要尾插的数据[-1结束]:

5 6 9 2 8 2 6 -1

***************************************************************

* [0] quit_system [1] Create_t [2] Create_h [3] showList *

* [4] del_back [5] del_front [6] insert_val [7] show_tail*

* [8] find [9] del_val [10] sortList [11] modify *

* [12]clear [13]destroy [14] resver [15]length *

* [16] next [17]prio *

***************************************************************

给出想要操作的序号:

3

5 6 9 2 8 2 6

***************************************************************

* [0] quit_system [1] Create_t [2] Create_h [3] showList *

* [4] del_back [5] del_front [6] insert_val [7] show_tail*

* [8] find [9] del_val [10] sortList [11] modify *

* [12]clear [13]destroy [14] resver [15]length *

* [16] next [17]prio *

***************************************************************

给出想要操作的序号:

8

输入要查找的数:

2

2

***************************************************************

* [0] quit_system [1] Create_t [2] Create_h [3] showList *

* [4] del_back [5] del_front [6] insert_val [7] show_tail*

* [8] find [9] del_val [10] sortList [11] modify *

* [12]clear [13]destroy [14] resver [15]length *

* [16] next [17]prio *

***************************************************************

给出想要操作的序号:

7

--链表的尾节点是:》6

***************************************************************

* [0] quit_system [1] Create_t [2] Create_h [3] showList *

* [4] del_back [5] del_front [6] insert_val [7] show_tail*

* [8] find [9] del_val [10] sortList [11] modify *

* [12]clear [13]destroy [14] resver [15]length *

* [16] next [17]prio *

***************************************************************

给出想要操作的序号:

10

***************************************************************

* [0] quit_system [1] Create_t [2] Create_h [3] showList *

* [4] del_back [5] del_front [6] insert_val [7] show_tail*

* [8] find [9] del_val [10] sortList [11] modify *

* [12]clear [13]destroy [14] resver [15]length *

* [16] next [17]prio *

***************************************************************

给出想要操作的序号:

3

2 2 5 6 6 8 9

***************************************************************

* [0] quit_system [1] Create_t [2] Create_h [3] showList *

* [4] del_back [5] del_front [6] insert_val [7] show_tail*

* [8] find [9] del_val [10] sortList [11] modify *

* [12]clear [13]destroy [14] resver [15]length *

* [16] next [17]prio *

***************************************************************

给出想要操作的序号:

14

***************************************************************

* [0] quit_system [1] Create_t [2] Create_h [3] showList *

* [4] del_back [5] del_front [6] insert_val [7] show_tail*

* [8] find [9] del_val [10] sortList [11] modify *

* [12]clear [13]destroy [14] resver [15]length *

* [16] next [17]prio *

***************************************************************

给出想要操作的序号:

3

9 8 6 6 5 2 2

***************************************************************

* [0] quit_system [1] Create_t [2] Create_h [3] showList *

* [4] del_back [5] del_front [6] insert_val [7] show_tail*

* [8] find [9] del_val [10] sortList [11] modify *

* [12]clear [13]destroy [14] resver [15]length *

* [16] next [17]prio *

***************************************************************

给出想要操作的序号:

16

输入想要找哪个一数的后继:

8

8 的后继是:6

***************************************************************

* [0] quit_system [1] Create_t [2] Create_h [3] showList *

* [4] del_back [5] del_front [6] insert_val [7] show_tail*

* [8] find [9] del_val [10] sortList [11] modify *

* [12]clear [13]destroy [14] resver [15]length *

* [16] next [17]prio *

***************************************************************

给出想要操作的序号:

12

--链表已被清空!

***************************************************************

* [0] quit_system [1] Create_t [2] Create_h [3] showList *

* [4] del_back [5] del_front [6] insert_val [7] show_tail*

* [8] find [9] del_val [10] sortList [11] modify *

* [12]clear [13]destroy [14] resver [15]length *

* [16] next [17]prio *

***************************************************************

给出想要操作的序号:

3

--链表为空

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值