15:01:58 2019-08-25
学习
22:43:01 2019-08-25
看的太慢了。。。马上要开学了


1 #include<stdio.h>
2 #include<malloc.h>
3 typedef struct Node* PtrToNode;
4 struct Node
5 {
6 int Data;
7 PtrToNode Pred; //前驱
8 PtrToNode Succ; //后继
9 };
10 PtrToNode Header;//头哨兵
11 PtrToNode Trailer;//尾哨兵 //前面写的双向链表只给 头部加了一个表头(哑节点) 现在给尾部也加一个哑节点
12 int size; //规模
13
14 void Init(); //初始化
15 PtrToNode InsertPred(int Element); //前插入
16 PtrToNode InsertSucc(int Element); //后插入
17 int Size(); //返回列表当前规模(节点总数)
18 PtrToNode First() { return Header->Succ; } //返回首节点位置
19 PtrToNode Last() { return Trailer->Pred;} //返回末节点位置
20 PtrToNode InsertAsFirst(int Element); //将元素E当首节点插入
21 PtrToNode InsertAsLast(int Element) { InsertBefore(Trailer, Element); } //将元素E当末节点插入
22 PtrToNode InsertBefore(PtrToNode P, int Element); //将元素E当作P的前驱元插入
23 PtrToNode InsertAfter(PtrToNode P, int Element); //将元素E当作P的后驱元插入
24 int Remove(PtrToNode P); //删除节点 返回删除的数据
25 int Disordered(); //判断所有节点是否有按非降序排列
26 void Sort(); //调整各节点的位置 使之按非降序排列
27 PtrToNode Find(int Element,int n,PtrToNode P); //查找目标元素E(从P(不包括)到P节点前n个元素) 失败时返回NULL
28 PtrToNode Search(int Element,int n,PtrToNode P); //在P节点前的n个元素中 查找E 返回不大于E且秩最大的节点
29 int DeDuplicate(); //剔除重复元素
30 int Uniquify(); //剔除重复元素
31 void Traverse(); //遍历列表
32
33
34
35 void Init()
36 {
37 Header = (PtrToNode)malloc(sizeof(Node));
38 Trailer = (PtrToNode)malloc(sizeof(Node));
39 Header->Succ = Trailer; Header->Pred = NULL;
40 Trailer->Pred = Header; Trailer->Succ = NULL;
41 size = 0;
42 }
43
44 //无序列表
45 int VisitByRank(int r) //寻秩序访问 效率低下
46 {
47 PtrToNode P =First(); //首节点出发
48 while (r--)
49 {
50 P = P->Succ;
51 }
52 return P->Data;
53 }
54
55 PtrToNode Find(int Element, int n, PtrToNode P) //查找目标元素E(从P(不包括)到P节点前n个元素) 失败时返回NULL
56 {
57 /*PtrToNode Ptr = P;
58 for (int i = 1; i < n + 1; i++)
59 {
60 Ptr = Ptr->Pred;
61 if (Ptr->Data == Element)
62 return Ptr;
63 }
64 return NULL;*/
65 while (n--)
66 if (Element ==(P = P->Succ)->Data) return P;
67 return NULL;
68 }
69
70 PtrToNode InsertBefore(PtrToNode P, int Element) //将元素E当作P的前驱元插入
71 {
72 PtrToNode Ptr = (PtrToNode)malloc(sizeof(Node));
73 Ptr->Data = Element;
74 Ptr->Succ = P; Ptr->Pred = P->Pred;
75 P->Pred = Ptr; Ptr->Pred->Succ = Ptr;
76 size++;
77 }
78 PtrToNode InsertAfter(PtrToNode P, int Element) //将元素E当作P的后继元插入
79 {
80 PtrToNode Ptr = (PtrToNode)malloc(sizeof(Node));
81 Ptr->Data = Element;
82 Ptr->Pred = P; Ptr->Succ = P->Succ;
83 P->Succ = Ptr; Ptr->Succ->Pred = Ptr;
84 size++;
85 }
86 //复制
87 void CopyNodes(PtrToNode P, int n)
88 {
89 Init(); //创造一个新的首尾节点
90 while (n--)
91 {
92 InsertAsLast(P->Data);
93 P = P->Succ;
94 }
95 }
96
97 int Remove(PtrToNode P) //删除节点
98 {
99 int Element = P->Data; //备份数据
100 P->Pred->Succ = P->Succ;
101 P->Succ->Pred = P->Pred;
102 free(P);
103 size--;
104 return Element; //返回删除节点
105 }
106
107 int Delete()
108 {
109 /*PtrToNode P1, P2;
110 P1=P2=Header->Succ;
111 while (size--)
112 {
113 P2 = P1->Succ;
114 Remove(P1); //这里写错了 如果按照我的想法应该用free
115 P1 = P2;
116 }
117 free(Header);
118 free(Trailer);*/ //憨憨博主的做法 这部分写的有问题 remove 会对size进行改变
119 int OldSize = size;
120 while (size)
121 {
122 Remove(Header->Succ);
123 }
124 free(Header);
125 free(Trailer);
126 return OldSize;
127 }
128
129 int DeDuplicate()
130 {
131 if (size < 2) return 0; //平凡情况
132 int OldSize = size;
133 PtrToNode P = First();
134 int r = 1;
135 while (Trailer!=(P=P->Succ))
136 {
137 PtrToNode Q = Find(P->Data, r, P);
138 Q ? Remove(Q) : r++; //删除前面的元素 如果删除后面的会出错 因为此时P为NULL
139 }
140 return OldSize - size;
141 }
142
143 //有序列表
144 int Uniquify() //O(n)
145 {
146 /*if (size < 2) return 0; //平凡情况
147 int OldSize = size;
148 PtrToNode P1, P2;
149 P1 = First(); P2 = P1->Succ;
150 while (Trailer!=P2)
151 {
152 if (P1->Data == P2->Data)
153 {
154 Remove(P2);
155 P2 = P1->Succ;
156 }
157 else
158 {
159 P1 = P2;
160 P2 = P1->Succ;
161 }
162 }
163 return OldSize - size;*/
164 //简化
165 if (size < 2) return 0; //平凡情况
166 int OldSize = size;
167 PtrToNode P1, P2;
168 P1 = First();
169 while (Trailer!=(P2=P1->Succ))
170 {
171 if (P1->Data!=P2->Data)
172 P1 = P2;
173 else
174 Remove(P2);
175 }
176 return OldSize - size;
177 }
178
179 PtrToNode Search(int Element, int n, PtrToNode P) //在P节点前的n个元素中 查找E 返回不大于E且秩最大的节点 为其它接口使用提供了方便
180 {
181 while (0<=n--) //等于0的情况 是为了处理在P节点前的n个元素中 没有查找到 返回P前第n+1个元素
182 {
183 if (Element >= (P = P->Pred)->Data)
184 break;
185 }
186 return P;
187 }
188
189 //排序算法
190
191 //选择排序 //O(n^2)
192 void SwapElement(PtrToNode P1, PtrToNode P2) //交换两个节点的元素
193 {
194 int Element = P1->Data;
195 P1->Data = P2->Data;
196 P1->Data = Element;
197 }
198 PtrToNode SelectMax(PtrToNode P, int n)
199 {
200 PtrToNode Max = P;
201 for (PtrToNode Cur = P; n > 1; n--)
202 {
203 if (Max->Data <= (Cur = Cur->Succ)->Data) //元素相同时也要返回后面的元素
204 Max = Cur;
205 }
206 return Max;
207 }
208 void SelectSort(PtrToNode P, int n) //将P后n个元素进行排序
209 {
210 PtrToNode head = P->Pred;
211 PtrToNode tail = P;
212 for (int i = 0; i < n; i++) tail = tail->Succ;
213 while (n>1)
214 {
215 //InsertBefore(tail, Remove(SelectMax(head->Succ, n)));
216 SwapElement(SelectMax(head->Succ, n),tail->Pred);
217 tail = tail->Pred;
218 n--;
219 /*优化
220 PtrToNode Max = SelectMax(head->Succ, n);
221 if (tail->Pred != Max)
222 SwapElement(Max, tail->Pred);
223 tail = tail->Pred;
224 n--;*/
225 }
226 }
227
228 //插入排序 最好O(n) 最坏O(n^2)
229 void InsertionSort(PtrToNode P,int n) //从位置P开始 到之后的n个元素
230 {
231 for (int r = 0; r < n; r++)
232 {
233 InsertAfter(Search(P->Data, r, P), P->Data);
234 P = P->Succ;
235 Remove(P->Pred);
236 }
237 }
