线性表
单向链表实现:
- 优点:便于插入和删除
- 缺点:查找数据需要遍历
声明
- 一个数据+一个指针
typedef struct LNode *List; struct LNode { int Data; List next; };
求表长
- 遍历表,当指向节点的指针为NULL时停止
int Length(List PtrL) { List p = PtrL; int j = 0; while (p) { p = p->next; j++; } return j; }
查找数据
- 当指针不为NULL或者未找到数据时,继续循环
按值查找
List Find(int X, List PtrL) { List p = PtrL; while (p!=NULL && p->Data != X)p = p->next; return p; }
按序号查找
List FindKth(int K, List PtrL) { List p = PtrL; int i = 1; while (p != NULL&&i < K) { p = p->next; i++; } if (i == K)return p; else return NULL; }
插入数据
- 当插在第一个位置时:创建节点,让该节点直接指向头结点。
- 当插在第i个位置时:创建节点,让该节点指向该位置的后一个节点,再让这个位置的节点指向插入的节点。
List Insert(int X, int i, List PtrL) { List p, s; if (i == 1) { s = (List)malloc(sizeof(struct LNode)); s->Data = X; s->next = PtrL; return s; } p = FindKth(i-1, PtrL); if (p == NULL) { printf("Error!"); return NULL; } else { s = (List)malloc(sizeof(struct LNode)); s->Data = X; s->next = p->next; p->Data = s; return PtrL; } }
删除数据
- 当删除头结点时,用一个临时指针指向头结点,将第二个结点当作头结点,再释放原头结点的内存。
- 当删除中间结点时,用一个临时指针指向该中间结点,该位置结点指向下一个结点,再释放要删除的结点的内存。
- p指针指向要删除结点的前一个结点,要注意指向的结点是否为NULL;
List Delete(int i,List PtrL) { List p, s; if (i == 1) { s = PtrL; if (PtrL != NULL)PtrL = PtrL->next; else return NULL; free(s); return PtrL; } p = FindKth(i - 1, PtrL); if (p == NULL) { printf("The %d node is not exited!",i-1); return NULL; } else if (p->next == NULL) { printf("The %d node is not exited!", i); return NULL; } else { s = p->next; p->next = s->next; free(s); return PtrL; } }
输出数据
void Print(List PtrL) { while (PtrL != NULL) { printf("%d ", PtrL->Data); PtrL = PtrL->next; } return; }
注意
- 自定义的线性表并不一定更要按标准,顾名思义,自定义线性表就是自定义,完全可以自己大胆改变线性表的内容。
循环链表
- 最后一个元素不指向空指针而是指向头节点,形成一个环,这样首尾相接的链表就称为循环链表。
优点
- 查找第一个元素和最后一个元素花费时间降为O(1)。
改变
- 最后一个元素指向头结点。与next原先指向空指针的操作均要改为头结点。
双向循环链表
- 在结点中同时储存两个指针,分别用于指向前驱和后继,同时最后一个指针指向头结点。
优点
- 便于查找前驱后继。
- 查找第一个元素和最后一个元素花费时间降为O(1)。
- 便于反向遍历。
实现代码
#include<iostream> #include<stdlib.h> using namespace std; typedef struct node Node; typedef struct node *link; struct node { int element; link left; link right; }; typedef struct dlist *List; typedef struct dlist Dlist; typedef struct dlist { int n; link leftEnd, rightEnd; link header; }; link NewNode() { link L; L = (link)malloc(sizeof(Node)); return L; } List ListInit() { node* y; List L = (List)malloc(sizeof(dlist)); y = NewNode(); y->left = y; y->right = y; L->header = y; L->n = 0; return L; } int ListRetrieve(int k, List L) { int i = 1; link p; p = L->header->right; if (k<1 || k>L->n)printf("out of bounds"); while (i < k) { p = p->right; i++; } return p->element; } int ListLocate(int x, List L) { int i = 0; link p; p = L->header->right; L->header->element = x; while (p->element!=x) { p = p->right; i++; } return ((p == L->header) ? 0 : i); } void ListInsert(int x, int k, List L) { int i = 0; link p, y; p = L->header; for (i = 1; i < k; i++) { p = p->right; } y = NewNode(); y->element = x; y->left = p; y->right = p->right; p->right->left = y; p->right = y; L->n++; return; } int ListDelete(int k, List L) { int x; link p; if (k<1 || k>L->n)printf("out of bounds"); p = L->header; int i = 1; for (i = 1; i < k; i++)p = p->right; p->left->right = p->right; p->right = p->left; x = p->element; free(p); return x; } void PrintList(List L) { link p; for (p = L->header->right; p != L->header; p = p->right) printf("%d ",p->element); return; }
来源:https://www.cnblogs.com/vancasola/p/7622821.html