线性表的存储表示有两种:顺序存储(顺序表,是用数组作为表的存储结构)和链表存储
顺序表优点:
- 无需为表示结点间的逻辑关系而增加额外的存储空间,存储利用率高
- 可以方便的进行随机存取顺序表中的任一结点,存取速度块
顺序表缺点:
- 表中插入或者删除某一元素时,为了保持其他元素相对次序不变,平均要移动一半的元素,运行效率低
- 难以确定合适的存储空间,多了造成浪费空间,少了则容易发生溢出
同样的,链表相比顺序,优缺点也就显现出来了。
滑动窗口(指针追赶):利用指针移动速度的不同实现
线性链表的其他变形:
- 循环链表:表尾结点的link不为NULL,而是指向链表的头结点。判断是否到达表尾 current->link == first。实例:求解约瑟夫环
- 双向链表:每个结点至少三个域,前驱指针、数据、后驱指针。做某些操作是应设置一个标识位去标识搜索方向。
静态链表:为数组中每个元素附加一个链接指针,就形成静态链表结构。允许我们不改变各元素的物理位置,只要重新链接就能够改变这些元素的逻辑顺序
因为正常的数组我们已经使用的够多了,但是链表这样指针形式的还是使用的非常少,这里我就以链表形式,实现单链表。
单链表分为两部分 指针域link 和 数据域data,各个结点之间用各结点的指针域link连接
1 #include<iostream> 2 using namespace std; 3 4 struct LinkNode{ 5 int data; 6 LinkNode *link; 7 LinkNode(LinkNode *ptr = NULL ){ 8 link = ptr; 9 } 10 LinkNode(const int& item, LinkNode *ptr = NULL){ 11 data = item; 12 link = ptr; 13 } 14 }; 15 16 class List { 17 public: 18 LinkNode *first; 19 public: 20 List(){ 21 first = new LinkNode; 22 } 23 List(const int& x){ 24 first = new LinkNode(x); 25 } 26 List(List& L){//复制构造函数 27 int value; 28 LinkNode *srcptr = L.getHead(); 29 LinkNode *destptr = first = new LinkNode; 30 while(srcptr->link != NULL){ 31 value = srcptr->link->data; 32 destptr->link = new LinkNode(value); 33 destptr = destptr->link; 34 srcptr = srcptr->link; 35 } 36 destptr->link = NULL; 37 }; 38 ~List(){ 39 makeEmpty(); 40 } 41 void makeEmpty(){//清空链表 42 LinkNode *q; 43 while(first->link != NULL){ 44 q = first->link; 45 first->link = q->link; 46 delete q; 47 } 48 }; 49 int Length() const{ 50 int len = 0; 51 LinkNode *p = first->link; 52 while( p != NULL){ 53 p = p->link; 54 len++; 55 56 } 57 return len; 58 }; 59 LinkNode *getHead() const {return first;} 60 LinkNode *Search(int x){ 61 LinkNode *p = first->link; 62 while(p!=NULL){ 63 if(p->data != x){ 64 p = p->link; 65 }else{ 66 break; 67 } 68 } 69 return p; 70 }; 71 LinkNode *Locate(int i){ 72 if(i<0) return NULL; 73 LinkNode *p = first->link; 74 int k = 0; 75 while(p != NULL && k < i){ 76 p = p->link; 77 k++; 78 } 79 return p; 80 } 81 bool getData(int i, int& x){ 82 if(i < 0) return NULL; 83 LinkNode *p = Locate(i); 84 if(p == NULL) return false; 85 else{ 86 x = p->data; 87 return true; 88 } 89 }; 90 bool setData(int i,int& x){ 91 if(i<0) return false; 92 LinkNode *p = Locate(i); 93 if(p!=NULL){ 94 p->data = x; 95 return true; 96 }else{ 97 return false; 98 } 99 }; 100 bool Insert(int i,int& x){ 101 LinkNode *p = Locate(i); 102 if(p == NULL) return false; 103 LinkNode *newNode = new LinkNode(x); 104 if(newNode == NULL) { 105 cout<<"插入失败,存储分配错误"<<endl; 106 exit(1); 107 } 108 109 newNode->link = p->link; 110 p->link = newNode; 111 return true; 112 }; 113 bool Remove(int i, int& x){ 114 LinkNode *p = Locate(i-1); 115 if(p == NULL || p->link == NULL){ 116 return false; 117 } 118 LinkNode *del = p->link; 119 p->link = del->link; 120 x = del->data; 121 delete del; 122 return true; 123 }; 124 bool Isempty() const{ 125 return first->link == NULL ? true : false; 126 } 127 bool IsFull()const { 128 if(first->link == NULL){ 129 return false; 130 }else{ 131 return true; 132 } 133 } 134 void Sort(); 135 void input(){ 136 }; 137 void output(){ 138 LinkNode *p = first->link; 139 if(p == NULL){ 140 cout<<"这是一个空链表"<<endl; 141 } 142 //cout<<"已经到输出了"<<endl; 143 int i=0; 144 while(p!=NULL){ 145 cout<<"链表第"<<i<<"个数据为"<<p->data<<endl; 146 i++; 147 p = p->link; 148 } 149 }; 150 }; 151 152 int main(){ 153 //定义的链表,第一个节是从 0 开始 154 LinkNode *first = new LinkNode;; 155 156 List list; 157 list.first = first; 158 cout<<first<<endl; 159 160 LinkNode *p = new LinkNode; 161 //添加两个结点 162 list.first->link = p; 163 p->data = 1; 164 LinkNode *p1 = new LinkNode; 165 p1->data = 2; 166 p->link = p1; 167 168 cout<<"该链表是为空:"<<list.Isempty()<<endl; 169 170 int i; 171 cout<<"在 1 的位置插入:"; 172 cin>>i; 173 cout<<"第0个元素之后插入成功?:"<<list.Insert(1,i)<<endl; 174 175 cout<<"1 位置的元素为:"<<list.Locate(1)->data<<endl; 176 cout<<"链表长度为:"<<list.Length()<<endl; 177 int o; 178 cout<<"设置 0 位置的元素值为:"; 179 cin>>o; 180 cout<<"设置 0 位置元素的值成功?:"<<list.setData(0,o)<<endl; 181 cout<<"---------------------"<<endl; 182 cout<<"输出单链表:"<<endl; 183 list.output(); 184 185 int t; 186 list.getData(1,t); 187 cout<<" 1 位置的是:"<<t<<endl; 188 list.makeEmpty();//清空链表 189 cout<<"该链表是为空:"<<list.Isempty()<<endl; 190 list.output();//输出链表 191 192 return 0; 193 }
运行截图: