数据结构
逻辑结构与物理结构
逻辑结构
数据对象中数据元素之间的相互关系
- 集合
- 线性
- 树形
- 图形
物理结构
数据的逻辑结构在计算机中的存储形式
- 顺序
- 链式
线性表
链表操作
code
typedef struct Node {
int data;
struct Node *next;
} Node;
int getElem(Node *L, int i) {
Node *p;
p = L->next;
int j = 1;
while (p && j < i) {
p = p->next;
j++;
}
if (p == nullptr || j > i)
return -1;
return p->data;
}
int insert(Node *L, int i, int target) {
int j = 1;
Node *p;
p = L;
while (p && j < i) {
p = p->next;
j++;
}
if (!p || j > i) {
return -1;
}
Node *tmp = (Node *) malloc(sizeof(Node));
tmp->data = target;
tmp->next = p->next;
p->next = tmp;
return 0;
}
int listDelete(Node *L, int i) {
int j = 1;
Node *p;
p = L;
while (p && j < i) {
p = p->next;
j++;
}
if (p->next == nullptr || j > i)
return -1;
Node *tmp = p->next;
p->next = tmp->next;
free(tmp);
return 0;
}
int createListHead(Node *L, int n) {
//头插法
Node *p;
int i = 0;
L = (Node *) malloc(sizeof(Node));
L->next = nullptr;
srand(time(0));
for (int i = 0; i < n; i++) {
p = (Node *) malloc(sizeof(Node));
p->data = rand() % 100;
p->next = L->next;
L->next = p;
}
return 0;
}
int createListTail(Node *L, int n) {
//尾插法
Node *p, *tmp;
srand(time(0));
L = (Node *) malloc(sizeof(Node));
L->next = nullptr;
p = L;
for (int i = 0; i < n; i++) {
tmp = (Node *) malloc(sizeof(Node));
tmp->data = rand() % 100;
p->next = tmp;
p = tmp;
}
p->next = nullptr;
return 0;
}
int reverseList(Node *L) {
Node *p, *q, *r;
if (L->next != nullptr)
p = L->next;
else
return -1;
L->next = nullptr;
q = nullptr;
while (p) {
r = p->next;
p->next = q;
q = p;
p = r;
}
L->next = p;
return -1;
}
排序
性质
- 元素的移动次数与关键字的初始排列次序无关的是:基数排序
- 元素的比较次数与初始序列无关是:选择排序
- 算法的时间复杂度与初始序列无关的是:直接选择排序
- 选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,而冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法
- 总排序趟数与初始状态无关的有:(除了快速排序和优化的冒泡,其他都是)
- 算法复杂度与初始状态无关的有:堆排序、归并排序、选择排序、基数排序
- 元素总比较次数与初始状态无关的有:选择排序、基数排序
- 元素总移动次数与初始状态无关的有:归并排序、基数排序。
选择排序
算法思想
选择排序,从头至尾扫描序列,找出最小的一个元素,和第一个元素交换,接着从剩下的元素中继续这种选择和交换方式,最终得到一个有序序列。
code
public class Selection {
public static void sort(int[] arr){
for(int i=0; i<arr.length-1; i++) {
int minPos = i;
for (int j = i; j < arr.length; j++) {
if (arr[j] < arr[minPos]) {
minPos = j;//找出当前最小元素的位置
}
}
if(arr[minPos]!=arr[i]) {
swap(arr,minPos,i);
}
}
}
public static void swap(int[] arr,int a,int b){
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
}
希尔排序
算法思想
希尔排序是记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
操作步骤
初始时,有一个大小为 10 的无序序列。
- 在第一趟排序中,我们不妨设 gap1 = N / 2 = 5,即相隔距离为 5 的元素组成一组,可以分为 5 组。
- 接下来,按照直接插入排序的方法对每个组进行排序。
在第二趟排序中,我们把上次的 gap 缩小一半,即 gap2 = gap1 / 2 = 2 (取整数)。这样每相隔距离为 2 的元素组成一组,可以分为 2 组。 - 按照直接插入排序的方法对每个组进行排序。
- 在第三趟排序中,再次把 gap 缩小一半,即gap3 = gap2 / 2 = 1。 这样相隔距离为 1 的元素组成一组,即只有一组。
- 按照直接插入排序的方法对每个组进行排序。此时,排序已经结束。
code
public static void shellSort(int a[]) {
int d= a.length;//gap的值
while (true){
d = d/ 2;//每次都将gap的值减半
for (int x = 0; x< d; x++) {
//对于gap所分的每一个组
for (int i = x+ d; i < a.length; i= i + d) {
//行插入排序
int temp= a[i];
int j;
for (j= i - d; j>= 0 && a[j] > temp;j = j - d){
a[j+ d] = a[j];
}
a[j+ d] = temp;
}
}
if (d==1) {
//gap==1,跳出循环
break;
}
}
}
直接插入排序
算法思想
将数组的第一个数认为是有序数组,从后往前(从前往后)扫描该有序数组,把数组中其余n-1个数,根据数值的大小,插入到有序数组中,直至数组中的所有数有序排列为止。这样的话,n个元素需要进行n-1趟排序!!!
操作步骤
4个数字4,6,7,5进行从大到小的排序
把第一个数4插入到空的有序数组中的第一个位置上,得到新数字序列4;
- 从后往前扫描有序数组,将第二个数字6和有序数组中的4进行比较,6大于4,此时将4后移一个位置。此时已经扫描完有序数组中的数,将6插入到4的前面(有序数组的第一个位置),得到新数字序列6,4;
- 从后往前扫描有序数组,先将第三个数字7和有序数组中的4进行比较,7大于4,此时将4后移一个位置;再将7和有序数组中的6进行比较,7大于6,此时将6后移一个位置。此时已经扫描完有序数组中的数,将7插入到6的前面(有序数组的第一个位置),得到新数字序列7,6,4;
- 从后往前扫描有序数组,先将第四个数字5和有序数组中的4进行比较,5大于4,此时将4后移一个位置;再将5和有序数组中的6进行比较,5小于6,由于有序数组就按照从大到小排列的,此时直接把5插入到4的前面即可!不需要再和7进行比较!最后,得到新数字序列7,6
code
#include<iostream>
#include<cstdio>
using namespace std;
#define N 5
int a[N];//有序数组
int main ( ) {
int i, k, x;
for (i=0; i<N; i++) {
scanf ("%d", &x);
for ( k=i; k>0; k-- ) {
/* 从后向前比较 */
if ( a[k-1] > x ) //x前面的数比它大
a[k]=a[k-1]; /* 将大数向后移动*/
else
break; /* 找到插入的位置,退出 */
}
a[k] = x; /* 完成插入操作 */
}
for (i=0; i<N; i++)
printf("%d ", a[i]);
return 0;
}
堆排序
int h[1000];
int n = 1000;
void siftDown(int i) {
int t, flag = 0;
while (i * 2 < n && flag == 0) {
if (h[i] < h[i * 2]) {
t = i * 2;
} else
t = i;
if (i * 2 + 1 <= n) {
if (h[t] < h[i * 2 + 1]) {
t = i * 2 + 1;
}
}
if (t != i) {
int tmp = h[t];
h[t] = h[i];
h[i] = tmp;
i = t;
} else
flag = 1;
}
}
void siftUp(int i) {
int flag = 0;
if (i == 1)
return;
while (i != 1 && flag == 0) {
if