链表是一种物理存储单元上非连续、非顺序的存储结构。//相较于顺序存储结构:数组。
链表可以是单(向)链表,也可以是双(向)链表。//双向链表可以说是单向链表上的改进,这样子方便对节点的前驱节点进行操作。
*(੭*ˊᵕˋ)੭*ଘ 也可以是循环链表,顾名思义,就是头尾相连的链表//目前是在做约瑟夫环的链表实现的时候用过。
本小文内容就单链表的 建立,遍历,查找,插入,删除 内容进行整理
struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } };
单链表的建立,一般有两种:头插法和尾插法。
ListNode* CreatelinklistA1() {//头插法,无头哨兵节点 ListNode* head = NULL, * p = NULL; int x; for (int i = 0; i < 5; i++) { cin >> x; p = new ListNode(x); p->next = head; head = p; } return head; }
ListNode* CreatelinklistA2() {//头插法,有哨兵节点 ListNode* head = NULL, * p = NULL; head = new ListNode(-1);//哨兵节点 int x; for (int i = 0; i < 5; i++) { cin >> x; p = new ListNode(x); if (head->next == NULL) head->next = p; else { p->next = head->next; head->next = p; } } }
ListNode* CreatelinklistB1() {//尾插法,无头哨兵节点 ListNode* head = NULL, * p = NULL,*end=NULL; int x; for (int i = 0; i < 5; i++) { cin >> x; p = new ListNode(x); if (end == NULL) { end = p; head = end; } else { end->next = p; end = p; } } return head; }
ListNode* CreatelinklistB2() {//尾插法,头哨兵节点 ListNode* head = NULL, * p = NULL,*end=NULL; head = new ListNode(-1); int x; for (int i = 0; i < 5; i++) { cin >> x; p = new ListNode(x); if (end == NULL) { end = p; head->next = end; } else { end->next = p; end = p; } }return head; }
链表的遍历
void DisplayList(ListNode *head) { while (head != NULL) {//这里是无哨兵节点的遍历,如果有的话,谨记第一个元素是从head->next开始的 cout << head->val << endl; head = head->next; } }
查找
ListNode* FindElement(ListNode* head, int num) { // ListNode* p; while (head != NULL) { if (head->val == num) return head; head = head->next; } return NULL; }
插入:
插入的操作=先查找,找到插入节点的位置,再把插入的节点的指针(以及前面节点的指针进行修改)
ListNode* InsertElement(ListNode* head, int num, int k)//在第k个元素后面插入 { if (k < 0) return NULL; ListNode* p,*pre,*q; q = new ListNode(num); pre = p = head; for (int i = 0; i < k; i++) { pre = p; p = p->next; } pre->next = q; q->next = p; return head; }
删除:
先查找,后删除,同样对指针进行处理
代码关键在于:pre->next=p->next; free(p);
如果是删除整个链表的话,可以摘一个,释放一个。p=head; head=head->next; free(p).