c 语言单向链表构造函数,数据结构之单向链表

66b52468c121889b900d4956032f1009.png

8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

基础知识

单向链表的游标实现和指针实现最大的不同是游标实现无法采用指针的方式连接到下一个节点,其只能通过数组下标的方式进行下一节点的索引,因此游标实现相比指针实现需要手动管理数组内存使用情况,本文直接采用《数据结构与算法分析:C语言描述》中的思路,不过本文使用了一个哑节点,代码中约定数组第0号节点用来模拟管理内存,1号节点作为哑节点,具体的定义和实现如下小节所示。

游标单向链表的定义和实现

由于游标实现中不能动态申请内存,因此函数中会预先分配一个固定大小的数组。具体实现见如下代码:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36template

struct

{

CursorNode() : next(0) {}

DataType data;

int next;

};

const int maxListSize = 100;

template

class

{

public:

CursorList();

~CursorList();

void MakeEmpty();

bool IsEmpty(); /*判断链表是否为空*/

bool IsLast(int inPosition); /*判断是否为最后一个元素*/

int FindElement(DataType value); /*查找一个元素并返回下标*/

int FindNthElement(int n); /*查找第n个元素并返回下标*/

void DeleteElement(DataType inData); /*删除一个节点*/

void DeleteNthElement(int n); /*删除第n个节点*/

void InsertElement(DataType inData, int n); /*插入一个节点*/

int Length(); /*返回链表长度*/

void PrintList(); /*打印链表*/

private:

int Alloc(); /*获取一个单位节点的空间数组小标索引,没有返回0*/

void Free(int nodeIndex); /*释放一个单位节点的空间*/

private:

const int dummyNode = 1; /*哑节点下标固定为1*/

CursorNode listNodes[maxListSize]; /*节点数组*/

int listSize; /*保存链表长度*/

int lastNode; /*保存最后一个节点下标*/

};

如上所示,在链表类中有四个数据成员和一个全局变量maxListSize,数据成员分别为dummyNode、listNodes、listSize和lastNode。maxListSize是指节点数组最大容量,listNodes是节点数组,listSize是当前链表大小,dummyNode是哑节点索引,lastNode保存最后一个节点的数组索引。

下面依次实现各函数:构造函数,0号节点作为内存管理头节点,1作为哑节点(因为0代表没有下一个节点)1

2

3

4

5

6

7

8

9

10template

CursorList::CursorList():dummyNode(1), listSize(0), lastNode(0)

{

for (int i = 0; i < maxListSize; i++) {

listNodes[i].next = i + 1;

}

listNodes[0].next = 2; /*跳过哑节点*/

listNodes[1].next = 0; /*哑节点初始下一节点指向空*/

listNodes[maxListSize-1].next = 0; /*最后一个节点下一个节点指向空*/

}析构函数,模拟内存回收1

2

3

4

5template

CursorList::~CursorList()

{

MakeEmpty();

}清空链表1

2

3

4

5

6

7

8

9

10

11

12

13

14

15template

void CursorList::MakeEmpty()

{

if (listSize <= 0 || listNodes[dummyNode].next == 0) {

return;

}

int tmp = 0;

while (listNodes[dummyNode].next != 0) {

tmp = listNodes[dummyNode].next;

listNodes[dummyNode].next = listNodes[tmp].next;

Free(tmp);

}

listSize = 0; lastNode = 0;

return;

}判断列表是否为空1

2

3

4

5

6

7

8template

bool CursorList::IsEmpty()

{

if (listSize <= 0 || listNodes[dummyNode].next == 0) {

return true;

}

return false;

}判断是否为最后一个元素1

2

3

4

5template

bool CursorList::IsLast(int inPosition)

{

return inPosition != 0 && inPosition == lastNode;

}查找一个元素并返回下标1

2

3

4

5

6

7

8

9

10

11

12template

int CursorList::FindElement(DataType value)

{

int cycleIter = listNodes[dummyNode].next;

while (cycleIter != 0) {

if (listNodes[cycleIter].data == value) {

return cycleIter;

}

cycleIter = listNodes[cycleIter].next;

}

return 0;

}查找第n个元素,dummy为第0个元素,返回地址或者01

2

3

4

5

6

7

8

9

10

11

12template

int CursorList::FindNthElement(int n)

{

if (n <= 0) {

return 0;

}

int cycleIter = listNodes[dummyNode].next;

while (--n > 0 && cycleIter != 0) {

cycleIter = listNodes[cycleIter].next;

}

return cycleIter;

}删除一个节点,如果不存在则不做任何事1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20template

void CursorList::DeleteElement(DataType inData)

{

int cycleIter = dummyNode;

while (listNodes[cycleIter].next != 0) {

if (listNodes[listNodes[cycleIter].next].data == inData) {

int tmp = listNodes[cycleIter].next;

listNodes[cycleIter].next = listNodes[tmp].next;

lastNode = lastNode == tmp ? cycleIter : lastNode;

Free(tmp); --listSize;

return;

}

cycleIter = listNodes[cycleIter].next;

}

if (listNodes[dummyNode].next == 0) {

lastNode = 0;

}

return;

}删除第n个节点,如果不存在则不做任何事1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22template

void CursorList::DeleteNthElement(int n)

{

if (n <= 0 || n > listSize) {

return;

}

int cycleIter = dummyNode;

while (listNodes[cycleIter].next != 0 && --n > 0) {

cycleIter =listNodes[cycleIter].next;

}

if (n <= 0) {

int tmp = listNodes[cycleIter].next;

listNodes[cycleIter].next = listNodes[tmp].next;

lastNode = lastNode == tmp ? cycleIter : lastNode;

Free(tmp); --listSize;

}

if (listNodes[dummyNode].next == 0) {

lastNode = 0;

}

return;

}插入一个节点, n<0或者>链表长度代表直接插到末尾,其他代表插到第n个节点后1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29template

void CursorList::InsertElement(DataType inData, int n)

{

int insertElement = Alloc();

if (insertElement == 0) {

return; /*空间不足*/

}

listNodes[insertElement].data = inData;

listNodes[insertElement].next = 0;

if (n < 0 || n >= listSize) {

/*插到末尾*/

if (lastNode == 0) {

lastNode = dummyNode;

}

listNodes[lastNode].next = insertElement;

lastNode = insertElement; ++listSize;

return;

}

int cycleIter = dummyNode;

while (n-- > 0 && cycleIter != 0) {

cycleIter = listNodes[cycleIter].next;

}

if (n <= 0) {

listNodes[insertElement].next = listNodes[cycleIter].next;

listNodes[cycleIter].next = insertElement; ++listSize;

}

return;

}申请一个单位空间函数1

2

3

4

5

6

7

8

9

10

11template

int CursorList::Alloc()

{

if (listNodes[0].next == 0) {

return 0;

/*没有空间了*/

}

int tmp = listNodes[0].next;

listNodes[0].next = listNodes[tmp].next;

return tmp;

}释放一个单位空间函数1

2

3

4

5

6

7

8

9

10template

void CursorList::Free(int nodeIndex)

{

if (nodeIndex <= 1 || nodeIndex >= maxListSize) {

return;

}

listNodes[nodeIndex].next = listNodes[0].next;

listNodes[0].next = nodeIndex;

return;

}返回链表长度1

2

3

4

5template

int CursorList::Length()

{

return listSize;

}打印链表1

2

3

4

5

6

7

8

9

10template

void CursorList::PrintList()

{

int cycleIter = listNodes[dummyNode].next;

while (cycleIter != 0) {

cout << listNodes[cycleIter].data << ";";

cycleIter = listNodes[cycleIter].next;

}

cout << endl;

}

代码测试

对上述代码进行简单地测试,测试代码如下:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78using namespace std;

int main()

{

CursorList Test;

Test.InsertElement('A', 0);

Test.InsertElement('B', 1);

Test.PrintList();

Test.InsertElement('C', 1);

Test.InsertElement('D', 7);

cout << Test.IsEmpty() << endl;

Test.PrintList();

Test.InsertElement('E', 3);

Test.InsertElement('F', 2);

Test.PrintList();

cout << Test.Length() << endl;

Test.DeleteElement('B');

Test.PrintList();

Test.DeleteElement('F');

Test.PrintList();

Test.DeleteElement('D');

Test.PrintList();

Test.DeleteElement('B');

Test.PrintList();

cout << Test.IsEmpty() << endl;

cout << Test.Length() << endl;

Test.InsertElement('A', 0);

Test.InsertElement('B', 1);

Test.InsertElement('C', 1);

Test.InsertElement('D', 7);

Test.InsertElement('E', 3);

Test.InsertElement('F', 2);

Test.PrintList();

Test.MakeEmpty();

Test.PrintList();

Test.InsertElement('A', 0);

Test.InsertElement('B', 1);

Test.InsertElement('C', 1);

Test.InsertElement('D', 7);

Test.InsertElement('E', 3);

Test.InsertElement('F', 2);

Test.PrintList();

int pTest = Test.FindElement('A');

pTest = Test.FindElement('E');

pTest = Test.FindElement('G');

pTest = Test.FindNthElement(4);

pTest = Test.FindNthElement(-1);

pTest = Test.FindNthElement(1);

pTest = Test.FindNthElement(10);

return 0;

}

参考文章

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值