数据结构(严版)课本代码重敲——第九十章

编程笔记 数据结构 第九十章

二叉搜索树

  1 #include <iostream>
  2 #include <string.h>
  3 #include <stdio.h>
  4 #include <stdlib.h>
  5 #include <stack>
  6 using namespace std;
  7 /*
  8     日期:2018/4/17
  9     题目:二叉搜索树
 10 */
 11 typedef int Elemtype;
 12 typedef struct BSTNode
 13 {
 14     int key;
 15     Elemtype data;
 16     struct BSTNode *lchild,*rchild;
 17 }BSTNode,*BSTree;
 18 
 19 // 1 创建时插入建立二叉搜索树
 20 void insertBSTree(BSTree &t,BSTree &p)
 21 {
 22 
 23     if (t == NULL)
 24     {
 25         t = p; // 根节点为空
 26     }
 27     else {
 28         if (p->data >= t->data)
 29             insertBSTree(t->rchild,p);
 30         else
 31             insertBSTree(t->lchild,p);
 32     }
 33 
 34 
 35 }
 36 void createBSTree(BSTree &t)
 37 {
 38     Elemtype x;
 39     BSTree p;
 40     int n ;
 41     cout<< "请输入N和待排序的数据"<< endl;
 42     cin >> n;
 43     for (int i = 0;i<n;i++)
 44     {
 45         cin >> x;
 46         p = (BSTree)malloc(sizeof(BSTNode));
 47         p->data = x;
 48         p->key = i+1;
 49         p->lchild = NULL;
 50         p->rchild = NULL;
 51         insertBSTree(t,p);
 52     }
 53 
 54 }
 55 // 中序遍历
 56 void inOrder(BSTree t)
 57 {
 58     if (t)
 59     {
 60        inOrder(t->lchild);
 61        cout << t->data << " ";
 62        inOrder(t->rchild);
 63     }
 64 }
 65 
 66 // 查找
 67 int searchBSTree(BSTree &t,Elemtype data)
 68 {
 69     if (t)
 70     {
 71         if (data == t->data)
 72             return t->key;
 73         else if (data > t->data)
 74             searchBSTree(t->rchild,data);
 75         else
 76             searchBSTree(t->lchild,data);
 77     }else
 78     return 0;
 79 }
 80 // 动态树表:树结构不是一次生成的,而是在查找过程中,当树中不存在关键字等于
 81 // 给定值得结点时再进行插入,新插入的结点一定是叶子结点。
 82 
 83 int searchBSTree_dynamic(BSTree t,Elemtype data,BSTree &p,BSTree &f)
 84 {
 85     if (t)
 86     {
 87         if (t->data == data)
 88         {
 89             p = t;
 90             return 1;
 91         }
 92         else
 93         {
 94             if (t->data > data)
 95                 searchBSTree_dynamic(t->lchild,data,p,t);
 96             else
 97                 searchBSTree_dynamic(t->rchild,data,p,t);
 98         }
 99 
100     }
101     else
102     {
103         p = f;
104         return 0;
105     }
106 
107 }
108 void insertBSTree_dynamic(BSTree &t,Elemtype data)
109 {
110     BSTree p=NULL,f = NULL; // p指向查找到的结点,f为未找到是时的父节点
111     BSTree s;
112     if (!searchBSTree_dynamic(t,data,p,f))
113     {
114         s = (BSTree)malloc(sizeof(BSTNode));
115         s->data = data;
116         s->lchild = NULL;
117         s->rchild = NULL;
118         // 在树中没找到时即要插入结点
119         if (p == NULL)
120         {
121             t = s; // t为空二叉树,插入的叶子结点即为根节点的特殊情况
122         }
123         else
124         {
125             if (data > p->data )
126                 p->rchild = s;
127             else
128                 p->lchild = s; // 插入新的叶子结点
129         }
130 
131     }
132 }
133 
134 /*
135 删除节点分为三种情况:
136 1 p的左右子树均空,直接修改父节点指针
137 2 p有一个子树,让该子树成为父节点的左子树
138 3 p的两个子树均不为空
139 递归找到该结点,然后删除
140 
141 */
142 
143 void deleteBST(BSTree &t,Elemtype data)
144 {
145     void deleteB(BSTree&);
146     if (t)
147     {
148         if (t->data == data)
149         {
150             deleteB(t);
151         }
152         else if (t->data > data)
153             deleteBST(t->lchild,data);
154         else
155             deleteBST(t->rchild,data);
156     }
157 }
158 int deleteB(BSTree &p)
159 {
160     BSTree q,s;
161     if (p->lchild == NULL &&p->rchild == NULL)
162     {
163         q = p;
164         p = NULL;
165         free(q);
166     }
167     else
168         if (p->lchild == NULL)
169         { // 只有左子树空
170             q = p;
171             p = p->rchild;
172             free(q);
173         }
174         else  // 只有右子树空
175         if (p->rchild == NULL)
176         {
177             q = p;
178             p = p->lchild;
179             free(q);
180         }
181         else // 均不空
182         {
183            s = p->lchild;
184            while (s->rchild!=NULL)
185                 s = s->rchild;
186            s ->rchild = p->rchild;
187            q = p;
188            p = p->lchild;
189            free(q);
190         }
191 }
192 // delete 和 free 的的区别?
193 int main()
194 {
195     BSTree t = NULL;
196     //createBSTree(t);
197     int n;
198     Elemtype x;
199     cout << "n" << endl;
200     cin >> n ;
201     for (int i=0;i<n;i++)
202     {
203         cin >> x;
204         insertBSTree_dynamic(t,x);
205     }
206     inOrder(t);
207     cout << "请输入要删除的数据" <<endl;
208     cin >> x;
209     deleteBST(t,x);
210     inOrder(t);
211 
212 
213     return 0;
214 }

 

二叉搜索树的复习

  1 #include <iostream>
  2 #include <string.h>
  3 #include <stdio.h>
  4 #include <stdlib.h>
  5 #include <stack>
  6 using namespace std;
  7 /* 二叉搜索树 复习
  8 1. 创建+插入
  9 2. 搜索
 10 3. 删除
 11 4. 遍历
 12 */
 13 
 14 typedef struct BSTNode
 15 {
 16     int key;
 17     struct BSTNode *lchild,*rchild;
 18 }BSTNode,*BSTree;
 19 
 20 int insertBSTree(BSTree &t,BSTree &p)
 21 {
 22     // 如果找到则返回指向关键字的指针,否则插入到树中
 23     if (t== NULL)
 24     {
 25         t = p;
 26         return 1;
 27     }else
 28     {
 29         if (t->key == p->key)
 30         {
 31             return 1;
 32         }else if (t->key > p->key)
 33             insertBSTree(t->lchild,p);
 34         else
 35             insertBSTree(t->rchild,p);
 36     }
 37 }
 38 void createBSTree(BSTree &t)
 39 {
 40     t = NULL;
 41     int n;
 42     cout << "请输入N:" <<endl;
 43     cin >> n;
 44     cout << "请输入N个数" << endl;
 45     int key;
 46     for (int i=0;i<n;i++)
 47     {
 48         cin >> key;
 49         BSTree p = (BSTree)malloc(sizeof(BSTNode));
 50         p->key = key;
 51         p->lchild = NULL;
 52         p->rchild  = NULL;
 53         insertBSTree(t,p);
 54     }
 55 }
 56 
 57 void preOrder(BSTree T)
 58 {
 59     if (T)
 60     {
 61         preOrder(T->lchild);
 62         cout << T->key << " ";
 63         preOrder(T->rchild);
 64     }
 65 }
 66 
 67 void deleteT(BSTree &p)
 68 {
 69     BSTree q;
 70     // 删除P指向的结点
 71     if (p->lchild == NULL && p->rchild == NULL )
 72     {
 73         q = p;
 74         p = NULL;
 75         free(q);
 76         return ;
 77     }
 78     if (p->lchild == NULL)
 79     {
 80         q = p;
 81         p = p->rchild;
 82         free(q); // free 和 delete 的区别
 83         // malloc - free C new - delete C++
 84     }
 85     else if (p->rchild == NULL)
 86     {
 87         q = p;
 88         p = p ->lchild;
 89         free(q);
 90     }
 91     else
 92     {
 93         // 左右子树均不为空时,P左子树的最右侧的结点+P的右子树
 94         BSTree s = p->lchild;
 95         while (s->rchild != NULL)
 96             s = s->rchild;
 97         s->rchild = p->rchild;
 98         q = p;
 99         p = p->lchild;
100         free(q);
101 
102     }
103 }
104 void deleteBSTNode(BSTree &t,int key)
105 {
106     if (t)
107     {
108         // t为空时则为未找到
109         if (t->key == key)
110             deleteT(t);
111         else if (t->key > key)
112             deleteBSTNode(t->lchild,key);
113         else
114             deleteBSTNode(t->rchild,key);
115     }
116 
117 }
118 int main()
119 {
120     BSTree t;
121     createBSTree(t);
122     preOrder(t);
123     cout << "key:" << endl;
124     int key;
125     cin >> key;
126     deleteBSTNode(t,key);
127     preOrder(t);
128 
129 
130     return 0;
131 }

 

哈希表的实现

 1 #include <iostream>
 2 #include <string.h>
 3 #include <stdio.h>
 4 #include <stdlib.h>
 5 #include <stack>
 6 #define SUCCESS 1
 7 #define UNSUCCESS -1
 8 #define NULLkey -65519
 9 
10 
11 using namespace std;
12 /*
13 哈希表
14 */
15 const int HashLength = 20;
16 typedef int Elemtype;
17 typedef struct
18 {
19     Elemtype *elem;
20     int count; // 当前元素个数
21 }HashTable;
22 
23 void initHashTable(HashTable &h)
24 {
25     h.elem = (Elemtype *)malloc(sizeof(Elemtype)*HashLength);
26     h.count = 0;
27     for (int i = 0;i<HashLength;i++)
28         h.elem[i] = NULLkey;
29 }
30 
31 int hash_f(int key)
32 {
33     return key%HashLength;
34 }
35 void insertHashTable(HashTable &h,int key)
36 {
37     int addr = hash_f(key);
38     while (h.elem[addr]!= NULLkey)
39     {
40         addr = (addr+1)%HashLength;
41     }
42     h.elem[addr] = key;
43     h.count++;
44 }
45 int searchHashTable(HashTable h,int key)
46 {
47     // 查找成功返回存储位置否则返回UNSUCCESS
48     int addr = hash_f(key);
49     while (h.elem[addr]!=key)
50     {
51         addr = (addr+1)%HashLength;
52         if (h.elem[addr] == NULLkey || addr == hash_f(key))
53             return UNSUCCESS;
54         // 如果线性探测再散列到NULLKEY或者转了一圈重新回到起点则没找到
55     }
56 
57     return addr;
58 }
59 int main()
60 {
61     int a[] = {14,1,68,27,55,19,20,84,79,23,11,10};
62     HashTable h;
63     initHashTable(h);
64     for (int i = 0;i<12;i++ )
65         insertHashTable(h,a[i]);
66     for (int i=0;i<12;i++)
67     {
68         int addr = searchHashTable(h,a[i]);
69         cout << a[i] << " : " << addr << endl;
70     }
71 
72 
73     return 0;
74 }

 

排序

分类:
1 插入类
- 直接插入
- 折半插入
- 希尔排序
2 交换类
- 冒泡排序
- 快速排序
3 选择排序
- 简单选择排序
- 堆排序
4 归并类
- 归并排序
5 基数排序

  1 #include <iostream>
  2 #include <string.h>
  3 #include <stdio.h>
  4 #include <stdlib.h>
  5 #include <stack>
  6 #define SUCCESS 1
  7 #define UNSUCCESS -1
  8 #define NULLkey = -65519
  9 
 10 
 11 using namespace std;
 12 /*
 13 排序
 14 */
 15 // 直接插入排序:每次都是在一个有序的序列中插入一个新的关键字
 16 void insertSort(int r[],int n) // 待排序关键字存储在1-n的位置
 17 {
 18     /*
 19     时间复杂度:
 20     1 最好情况:仅有外层循环 O(n)
 21     2 最坏情况:n*(n-1)/2 O(n^2)
 22     空间复杂度:
 23     辅助存储空间仅有temp,故为O(1)
 24     */
 25     int temp;
 26     for (int i=1;i<=n;i++)
 27     {
 28         temp = r[i];// 存放待插入关键字
 29         int j = i-1;
 30         while (r[j] > temp && j > 0)
 31         {
 32             r[j+1] = r[j];
 33             j--;
 34         }
 35         r[j+1] = temp;
 36 
 37     }
 38 }
 39 
 40 void binsertSort(int r[],int n)
 41 {
 42     /*
 43     和直接插入排序的区别是:查找插入位置所花的时间大大减小
 44     */
 45     for (int i=1;i<=n;i++) // i = 1 时已经为有序数列
 46     {
 47         r[0] = r[i] ; // r[0] 空余空间中存放当前待插入关键字
 48         int low = 1,high = i-1; // 当前的有序序列为1-i-1;
 49         while (low <= high)
 50         {
 51             int mid = (low + high)/2;
 52             if (r[mid] >= r[0])
 53             {
 54                 high = mid-1;
 55             }
 56             else
 57                 low = mid+1;
 58         }
 59         // 之所以让low = high时再进入循环:比较当前关键字和high/low指向关键字的大小
 60         // 离开循环时low = high+1,low指向位置即为待移动的位置
 61         for (int j=i-1;j>=low;j--)
 62             r[j+1] = r[j];
 63         r[low] = r[0];
 64 
 65     }
 66 }
 67 // 希尔排序
 68 void shellInsert(int r[],int n,int dlta)
 69 {
 70     int j;
 71     for (int i = 1+dlta; i<=n ; i++)
 72     { // 循环 n - 1 - dlta 次 = 子序列的个数
 73         if (r[i] < r[i-dlta])
 74         {
 75             r[0] = r[i];
 76             for (j = i-dlta ; j>0 && r[j] > r[0] ; j = j-dlta )
 77                 r[j+dlta] = r[j];
 78             r[j+dlta] = r[0];
 79         }
 80     }
 81 }
 82 void shellSort(int r[],int dlta[],int n,int t )
 83 {
 84     /*
 85     缩小增量排序:对r[n]进行增量为dlta[t]的排序过程
 86     思想:直接插入排序适合基本有序的序列,希尔排序的每趟排序都会使整个序列变得更加有序,
 87     等整个序列基本有序后,最后进行一趟直接插入排序,效率会更高。
 88     注意:1.希尔排序是不稳定的。
 89     2.增量序列的最后一个值一定取1,增量序列中的值尽量没有除1之外的公因子
 90     */
 91     for (int i = 0;i<t;i++)
 92     {
 93         shellInsert(r,n,dlta[i]);
 94     }
 95 }
 96 void bubbleSort(int r[],int n)
 97 {
 98     /*
 99     外层比较n-1次,内层比较n-i次
100     时间复杂度:O(N^2)
101     空间复杂度:O(1)
102     */
103     int flag;
104     for (int i = 1;i<n;i++)
105     {
106         flag = true;
107         for (int j = 1;j<=n-i;j++)
108         {
109             if (r[j] > r[j+1])
110             {
111                 int temp = r[j];
112                 r[j] = r[j+1];
113                 r[j+1] = temp;
114                 flag = false;
115             }
116         }
117         if (flag) // 没发生交换说明有序
118             break;
119     }
120 }
121 // 快速排序之合并版
122 /*
123 通常,快速排序是同量级O(nlogn)的排序方法中,平均性能最好。
124 但若初始记录序列按关键字有序或基本有序时,快速排序将退化为起泡排序。
125 空间复杂度:栈
126 */
127 void quickSort(int r[],int low,int high)
128 {
129     int i = low,j = high;
130     if (low < high)
131     {
132         while (i<j)
133         {
134             r[0] = r[low];//枢纽
135             while (r[j]>r[0] && i < j)
136                 j -- ;
137             if (i < j)
138             {
139                 // 此时r[j] < r[0] 交换
140                 r[i] = r[j];
141                 i++;
142             }
143             while (i < j && r[i] < r[0] )
144                 i++;
145             if (i<j)
146             {
147                 r[j] = r[i];
148                 j--;
149             }
150         }
151         r[i] = r[0];// 将枢纽定在最终位置
152         quickSort(r,low,i-1);
153         quickSort(r,j+1,high);
154     }
155 }
156 
157 // 快速排序之分离版
158 int Partition(int r[],int low,int high)
159 {
160     while (low<high)
161     {
162         r[0] = r[low];
163         while (low < high && r[high] > r[0]  )
164             high -- ;
165         if (low < high)
166         {
167             r[low] = r[high];
168             low++;
169         }
170         while (low<high && r[low] < r[0])
171             low++;
172         if (low <high)
173         {
174             r[high] = r[low];
175             high--;
176         }
177     }
178     r[low] = r[0];
179     return r[0];
180 }
181 void qsort(int r[],int low,int high)
182 {
183     if (low < high)
184     {
185         int flag = Partition(r,low,high); // 一分为二并得到枢纽
186         qsort(r,low,flag -1);
187         qsort(r,flag+1,high);
188     }
189 }
190 void print(int r[],int n)
191 {
192     for (int i=1;i<=n;i++)
193         cout << r[i] <<' ';
194     cout << endl;
195 }
196 // 简单选择排序
197 void selectSort(int r[],int n)
198 {
199     int i,j,k;
200     for (i=1;i<=n-1;i++)
201     {
202         k = i;
203         for (j=i;j<=n;j++)
204         {
205             if (r[j]<r[k])
206             {
207                 k = j;
208             }
209         }
210         if (k!=i)
211         {
212             r[0] = r[i];
213             r[i] = r[k];
214             r[k] = r[0];
215         }
216     }
217 }
218 /*
219 堆排序:定义:非叶子结点的值都不大于(或不小于)其左右孩子结点的值。
220 将无序序列调整为完全二叉树形式的堆,根节点为最大值或最小值。
221 通过堆找到最大最小值后放在队列的尾部,将无序队列调整为有序队列。
222 
223 执行过程:
224 1 层次遍历法建立初始堆,找到第一个非叶子结点,按照从右往左,从下往上的顺序,
225 依次判断是否满足堆定义(假设为大顶堆,即孩子结点的数值是否都小于根节点)。
226 如不满足则选择孩子中较大的结点和根节点交换,同时判断下移的根节点的值是否满足定义。
227 2 将当前无序序列的第一个值和最后一个值交换,有序序列中增加一个值。判断和根节点交换的
228 新节点是否满足堆定义并进行调整。
229 
230 时间复杂度:
231 */
232 void shift(int r[],int low,int high)
233 {
234     int temp = r[low];
235     int i = low,j = 2*i;
236     while (j<=high)
237     {
238         if (j<high && r[j] < r[j+1])
239         {
240             j = j+1; // 选择I节点的孩子中较大的一个
241         }
242         if (temp < r[j])
243         {
244             r[i] = r[j];
245             i = j;
246             j = j*2;
247         }
248         else
249             break;
250     }
251     r[i] = temp;
252 }
253 void heapSort(int r[],int n)
254 {
255     // 1. 找到最后一个非终端节点,从右向左,从下向上进行调整,建立初始堆
256     int i;
257     for (i = n/2; i >=1 ;i--)
258     {
259         shift(r,i,n);
260     }
261     // 2. 将一次调整后的最大值和无序序列的最后一个值交换
262     for (i = n;i>=2;i--) // 进行n-1次排序
263     {
264         r[0] = r[1];
265         r[1] = r[i];// r[i]为最后一个
266         r[i] = r[0];
267         shift(r,1,i-1);//在减小了一个关键字的无序序列中进行调整
268     }
269 
270 }
271 int main()
272 {
273     int n ;
274     cin >> n;
275     int r[n];
276     for (int i=1;i<=n;i++)
277         cin >>r[i];
278     //insertSort(r,n);
279     //binsertSort(r,n);
280 //    bubbleSort(r,n);
281     //quickSort(r,1,n);
282 //    selectSort(r,n);
283 heapSort(r,n);
284     print(r,n);
285 
286 
287 
288 
289     return 0;
290 }

 

posted @ 2018-08-21 09:31  暴走的二萌  阅读(390)  评论(0编辑  收藏  举报