单向循环链表
注意:
在插入和删除的操作中,一定要把链表的头和尾拿出来单独分析! 由于链表在第一次完整连接后(比如下面程序中的PushBack函数),每个节点在链表中的内存地址已经固定了下来,比如上图中,b里保存的指针始终就是指向c的next的地址,c中保存的指针始终就是指向d的next的地址,d中保存的指针始终是指向head的地址,所以即使在a,b间插入一个元素e,也不会影响b,c,d节点指针的指向。所以只要不是有关处理头尾元素的操作,都不需要从头到尾地把链表重新连接一遍!因为位置在第一次连接的时候就已经固定了!
1 //CircleList.h 2 3 #pragma once 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 8 typedef struct Node 9 { 10 int element; 11 Node *next; 12 }Node; 13 14 typedef struct CircleList //单向循环链表 15 { 16 Node *head; 17 int length; 18 }CircleList; 19 20 void InitList(CircleList *cir); //创建循环链表 21 22 Node* GetPrev(CircleList *cir, Node* q); //获取节点q前驱元素的指针 23 24 Node* GetBack(CircleList *cir, Node* q); //获取节点q后继元素的指针 25 26 Node* BackElem(CircleList *cir); //返回指向尾节点的指针 27 28 void PushBack(CircleList *cir, int elem); //向链表尾部添加元素 29 30 void InsertElem(CircleList *cir, int position, int elem); //在position的前一个位置处插入元素 31 32 void DeleteElem(CircleList *cir, int position); //删除position位置处的元素 33 34 void ClearList(CircleList *cir); //清空循环链表 35 36 void PrintListFromFirst(CircleList *cir); //从第一个元素开始遍历循环链表 37 38 void PrintListFromPosition(CircleList *cir, int position); //从第position处的元素开始循环遍历整个链表
1 //CircleList.c 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include "CircleList.h" 6 7 void InitList(CircleList *cir) //创建循环链表 8 { 9 cir->length = 0; 10 cir->head = (Node*)malloc(sizeof(Node)); 11 cir->head->next = NULL; 12 } 13 14 Node* GetPrev(CircleList *cir, Node* q) //获取节点q前驱元素的指针 15 { 16 if (cir->head->next == q) 17 { 18 printf("该节点没有前驱元素!\n"); 19 return NULL; 20 } 21 Node *p = cir->head; 22 for (int i = 1; i <= cir->length; ++i) 23 { 24 p = p->next; 25 if (p->next == q) 26 return p; 27 } 28 } 29 30 Node* GetBack(CircleList *cir, Node* q) //获取节点q后继元素的指针 31 { 32 if (q == BackElem(cir)) 33 { 34 printf("该节点没有后继元素!\n"); 35 return NULL; 36 } 37 Node *p = cir->head; 38 for (int i = 1; i <= cir->length; ++i) 39 { 40 p = p->next; 41 if (q->next == p) 42 return p; 43 } 44 } 45 46 Node* BackElem(CircleList *cir) //返回指向尾节点的指针 47 { 48 Node *p = cir->head; 49 if (cir->length == 0) 50 return p; 51 for (int i = 1; i <= cir->length; ++i) 52 p = p->next; 53 return p; 54 } 55 56 void PushBack(CircleList *cir, int elem) //向链表尾部添加元素 57 { 58 Node *NewNode = (Node*)malloc(sizeof(Node)); 59 NewNode->element = elem; 60 Node *p = BackElem(cir); 61 p->next = NewNode; 62 NewNode->next = cir->head->next; 63 ++cir->length; 64 } 65 66 void InsertElem(CircleList *cir, int position, int elem) //在position的前一个位置处插入元素(head的position为0) 67 { 68 if (position > cir->length + 1 || position < 1) 69 { 70 printf("插入失败!请在合理的范围内插入元素!\n"); 71 return; 72 } 73 if (position == cir->length + 1 || position == 1) 74 { 75 Node *q = BackElem(cir); 76 Node *NewNode = (Node*)malloc(sizeof(Node)); 77 NewNode->element = elem; 78 q->next = NewNode; 79 NewNode->next = cir->head->next; 80 if (position == 1) 81 cir->head->next = NewNode; 82 ++cir->length; 83 return; 84 } 85 Node *p = cir->head; 86 for (int i = 1; i <= position - 1; ++i) 87 p = p->next; //获取position前一个位置处的指针p 88 Node *NewNode = (Node*)malloc(sizeof(Node)); 89 NewNode->element = elem; 90 NewNode->next = p->next; 91 p->next = NewNode; 92 ++cir->length; 93 return; 94 } 95 96 97 void DeleteElem(CircleList *cir, int position) //删除position位置处的元素 98 { 99 Node *p = cir->head; 100 if (position == 1) 101 { 102 p = p->next; 103 cir->head->next = p->next; 104 Node *q = BackElem(cir); 105 q->next = p->next; 106 free(p); 107 --cir->length; 108 return; 109 } 110 if (position == cir->length) 111 { 112 Node *q = BackElem(cir); 113 Node *p = GetPrev(cir, q); //令p指向倒数第二个元素 114 p->next = cir->head->next; 115 free(q); 116 --cir->length; 117 return; 118 } 119 for (int i = 1; i <= position - 1; ++i) 120 p = p->next; //获取position前一个位置处的指针p 121 Node *q = p->next; 122 p->next = q->next; 123 free(q); 124 --cir->length; 125 return; 126 } 127 128 129 void ClearList(CircleList *cir) //清空循环链表 130 { 131 int temp = cir->length; //删除过程中cir->length时刻变化,所以应该先将其原始值保存下来 132 for (int i = 1; i <= temp; ++i) 133 { 134 DeleteElem(cir, 1); //删除temp次1号节点,即可把整个链表清空 135 } //删除过程中length已经在一直自减,所以不需要添加额外的length自减语句 136 } 137 138 void PrintListFromFirst(CircleList *cir) //从第一个元素开始遍历循环链表 139 { 140 Node *p = cir->head; 141 for (int i = 1; i <= cir->length; ++i) 142 { 143 p = p->next; 144 printf("%d ", p->element); 145 } 146 } 147 148 void PrintListFromPosition(CircleList *cir, int position) //从第position处的元素开始循环遍历整个链表 149 { 150 Node *p = cir->head; 151 for (int i = 1; i <= position; ++i) 152 p = p->next; //获取position位置处的指针p 153 154 Node *org = p; //用org记录p的原始位置,用于作为循环遍历的终止条件 155 do 156 { 157 printf("%d ", p->element); 158 p = p->next; 159 } while (p != org); 160 }
1 //main.c 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include "CircleList.h" 6 7 int main() 8 { 9 CircleList cir; 10 InitList(&cir); 11 PushBack(&cir, 1); 12 PushBack(&cir, 2); 13 PushBack(&cir, 3); 14 PushBack(&cir, 4); 15 PushBack(&cir, 5); 16 PushBack(&cir, 6); 17 PushBack(&cir, 7); 18 PushBack(&cir, 8); 19 InsertElem(&cir,5,777); 20 21 // ClearList(&cir); 22 // InsertElem(&cir, 5, 666); 23 // DeleteElem(&cir,8); 24 Node *p = cir.head -> next; 25 // Node* p =BackElem(&cir); 26 printf("%d\n", p->element); 27 Node *q = GetBack(&cir, p); 28 printf("%d\n", q->element); 29 Node *q2 = GetPrev(&cir, q); 30 printf("%d\n", q2->element); 31 // DeleteElem(&cir,7); 32 // PrintListFromFirst(&cir); 33 // PrintListFromPosition(&cir,8); 34 // printf("%d", cir.length); 35 36 return 0; 37 }