本文最后更新于 2026-05-31T13:56:40+08:00
1. 线性表
同类型数据结构的有序数列
每个元素仅有一个直接前驱和直接后继(除了表头和表尾)
1.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 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 class LinearList { private : int *data[MAXSIZE]; int size; public : LinearList (int initialCapacity=MAXSIZE){ data=new int [innitialCapacity]; int size=0 ; int capacity=MAXSIZE; } ~LinearList (){ delete []data; } int find_pos (int index) { if (inidex<0 || index>=size) return NULL ; else return data[index]; } int find_value (int value) { result=-1 ; for (int i=0 ;i<size;i++){ if (value==data[i]){ result=i; break ; } } return result; } void insert (int index, const int & value) { if (index<0 || index>size || size==MAXSIZE){ cout<<"error" <<endl; return 0 ; } for (int i=size;i>index;--i) data[i]=data[i-1 ]; data[index]=value; size++; return ; } void doublespace{ newcapacity=capacity*2 ; int *newData = new int [newcapacity]; for (int i=0 ;i<size;i++) newData[i]=data[i]; delete [] data; data=newData; capacity=newcapacity; } void remove (int index) { if (index<0 || index>=size){ cout<<"error" <<endl; return ; } for (int i=index;i<size-1 ;i++) data[i]=data[i+1 ]; size--; return ; } }
1.2 线性表的链表存储 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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 class Node { public : int data; Node *next; Node (int val){ data=val; next=NULL ; return ; } }class LinkedList { public : Node*head; LinkedList (){ head=NULL ; } ~LinkedList (){ while (head!=NULL ){ Node *temp=head; head=head->next; delete temp; } } bool search (int val) { Node *current=head; while (current!=NULL ){ if (current->data==val) return true current=current->next; } return false ; } int get (int pos) { if (pos<0 || head=NULL ){ cout<<"error" <<endl; return -1 ; } Node *current=head; int count=0 ; while (current!=NULL && count<pos){ current=current->next; count++; } if (current==NULL ){ cout<<"Position is out of range!" <<endl; return -1 ; } return current->data; } void insert (int pos, int val) { if (pos<0 ){ cout<<"invalid position" <<endl; return ; } Node *newNode = new Node (val); if (pos==0 ){ newNode->next=head; head=newNode; } else { Node *current=head; int count=0 ; while (current!=NULL && count<pos-1 ){ current=current->next; count++; } if (current==NULL ){ cout<<"Position is out of range!" <<endl; delete newNode; return ; } newNode->next=current->next; current->next=newNode; } } void remove (int pos) { if (pos<0 || head=NULL ){ cout<<"invalid position or list is empty" <<endl; return ; } Node *temp; if (pos==0 ){ temp=head; head=head->next; delete temp; } else { Node *current=head; int count=0 ; while (current!=NULL && count<pos-1 ){ current=current->next; count++ } if (current==NULL || current->next==NULL ){ cout<<"position is out of range" <<endl; return ; } temp=current->next; current->next=temp->next; delete temp; } } }
反转链表:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 void reverse (Node *head) { Node *prev=NULL ; Node *cur=head; Node *next=NULL ; while (current!=NULL ){ next=cur->next; cur->next=prev; prev=cur; cur=next; } head=prev; }
1.3 链表变体
单循环链表 :末节点的next指向头结点,从表中任意一个节点出发,都可以沿next指针遍历所有节点 应用:约瑟夫环
双向链表 :每个节点有prior和next两个指针,分别指向直接前驱和直接后继结点。空双向链表只有头尾结点。可以根据待查元素在前半段还是后半段决定自head向后还是自tail向前,可通过参数length辅助判断
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 class Node { public : int data; Node *next; Node *prev; Node (int val){ data=val; next=NULL ; prev=NULL ; } }class LinkedList { private : Node *head; Node *tail; public : LinkedList (){ head=new Node (0 ); tail=new Node (0 ); head->next=tail; tail->next=head; } void insert () { Node *tmp=new Node (); tmp->data=x; tmp->prev=p; tmp->next=p->next; tmp->prev->next=tmp; tmp->next->prev=tmp; } }
双向循环链表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Node { public : int data; Node *next; Node *prev; Node (int val){ data=val; next=NULL ; prev=NULL ; } }class LinkedList { private : Node *head; public : LinkedList (){ head=NULL ; } }
2. 广义表 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 template <typename T>class GNode { protected : union { T data; GNode<T> *sublist; }u_region; GNode<T> *next; };template <typename T> calss GCommonNode : public GNode<T>{ public : GCommonNode (T value){ this ->u_region.data=value; this ->next=NULL ; } };template <typename T>class GSublistNode : public GNode<T>{ public : GSublistNode (GNode<T> *sublist){ this ->u_region.sublist=sublist; this ->next=NULL ; } }
2.1 多重链表 结点有多个指针域
2.2 稀疏矩阵存储 使用十字链表:定义head结点和term结点。head结点管理矩阵的每一行每一列,term结点管理矩阵的每个值。每一行每一列均构造成循环链表形式。
3. 字符串
字符串由零个或多个字符串组成的有限序列
串名,串值,串长
空字符串:字符串长度为0,仍然是一个字符串
空格字符串:有一个或一个以上的空格组成的字符串,长度为空格个数
单字符串:只有一个字符
字符串相等:长度相同+对应位置字符完全相同
子串:任意连续字符组成的子序列,位置用子串第一个字符在主串中的位置表示
主串:包含子串的字符串
仅考虑字符串的顺序存储
静态存储:容易引发截断
动态数组:==常见错误:如对字符串”cjy”的存储,3个字符加上结束标志符”\0” ,共占用4个字节。但是字符串长度仍为3,结束符不算入内。==
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 class sstring { private : char *str; int maxSize; public : sstring (int size){ if (size<0 ){ cout<<"error" <<endl; return ; } str=new char [size]; maxSize=size; str[0 ]='\0' ; } sstring subString (int pos, int len) const { if (pos<0 ){ cout<<"error" <<endl; return ; } int i=0 ; sstring *tmp = new sstring (len+1 ); for (; i<len && str[pos+i]!='\0' ;i++){ tmp->str[i]=str[pos+i]; } tmp->str[i]='\0' ; return *tmp; } bool equal (const sstring &t) const { int i=0 ; if (this ->length ()!=t.length ()) return false ; while (str[i]!='\0' ){ if (str[i]!=t.str[i]) return false ; else i++; } return true ; } }
注意: 字符串s和t相互赋值时,可能使用s.str=t.str,但是导致这连个数组在后续操作中同步变化,即对s操作时,t也会动,正确方法是s.str[i]=t.str[i]
模式匹配: s为主串,匹配串称为模式
BF算法:暴力匹配,分别将主串的每一个位置认作匹配的开始,然后逐一匹配,若不成功,继续下一个位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 int sstring::BF_Find (const sstring &t, int start) { int i=0 ,j=0 ; int pos=-1 ; int n=this ->length (); int m=t.length; int curStart=start; while (curStart<=n-m){ i=curStart; while ((j<m)&&(str[i]==t.str[j])){ i++; j++; } if (j==m){ pos=curStart; break ; } curStart++; j=0 ; } return pos; }
时间复杂度分析: 最好情况:
一次匹配成功,o(m)
全部第一个字符匹配不成功,o(n) 最坏情况: 每次都是模式的最后一个字符匹配失败,导致不成功,时间为o((n-m)m)