代码部分
一、线性表
1、线性表的基本操作
1.1 线性表的顺序存储类型
静态分配
#define MaxSize 50 // 定义线性表最大长度
typedef struct{
ElemType data[MaxSize]; // 顺序表的元素
int length; // 顺序表的当前长度
}SqList; // 顺序表的类型定义
动态分配
#define InitSize 100 // 表长度的初始定义
typedef struct{
ElemType *data; // 指示动态分配数组的指针
int MaxSize,length; // 数组最大容量和个数
}SqList; // 类型定义
C的初始动态分配语句为
L.data = (ElemType *)malloc(sizeof(ElemType)* InitSize);
1.2 顺序表上基本操作实现
1.2.1 插入操作
在L中位置i插入元素
bool ListInsert(SqList &L, int i, ElemType e){
if(i < 1 || i > L.length + 1){ // 判断i是否有效
return false;
}
if(L.length >= MaxSize){ // 判断当前存储空间是否已满
return false;
}
for(int j = L.length; j >= i; j--){ // 将第i个元素及之后的元素后移
L.data[j] = L.data[j - 1];
}
L.data[i - 1] = e; // 在位置i插入元素
L.length++; // 线性表长度+1
return ture;
}
1.2.2 删除操作
在L中删除位置i的元素
bool ListInsert(SqList &L, int i, ElemType e){
if(i < 1 || i > L.length ){ // 判断i是否有效
return false;
}
e = L.data[i - 1]; // 记录删除元素
for(int j = i; j < length; j++){ // 将第i个元素之后的元素前移
L.data[j - 1] = L.data[j];
}
L.length--; // 线性表长度-1
return ture;
}
1.2.2 按值查找(顺序查找)
int LocateElem(SqList L, ElemType e){
for(int i = 0; i < L.length; i++){
if(L.data[i] == e){
return i + 1; // 查找成功
}
}
return 0; // 退出循环,查找失败
}
2、课后大题
2.1
bool DeleteElem(SqList &L, ElemType &value){
int k = 0;
if(L.length == 0){
return false;
}
value = L.data[0];
for(int i = 1; i < L.length; i++){
if(L.data[i] < value){
value = L.data[i];
k = i;
}
}
L.data[k] = L.data[L.length - 1];
}
L.length--;
return 0; // 退出循环,查找失败
}
2.2
void reverse(SqList &L){
ElemType temp;
for(int i = 0; i < L.length / 2; i++){
temp = L.data[i];
L.data[i] = L.data[L.length - i - 1];
L.data[L.length - i - 1] = temp;
}
}
2.3
// 方法一
void DeleteX(SqList &L, ElemType x){
if(L.length == 0){
return false;
}
int j = 0;
for(int i = 0; i < L.length; i++){
if(L.data[i] != x){
L.data[j] = L.data[i];
j++;
}
}
L.length = j + 1;
}
// 方法二
void DeleteX(SqList &L, ElemType x){
if(L.length == 0){
return false;
}
int i = 0, k = 0;
while(i < L.length){
if(L.data[i] == x){
k++;
}
else{
L.data[i - k] = L.data[i]; // 当前元素前移k个位置
}
i++;
}
L.length -= k;
}
2.4
此题意在有序顺序表的整体删除,但较麻烦,故采用上题方法一
bool DeleteElem(SqList &L, int s, int t){
if(s > t || L.length == 0){
return false;
}
int j = 0;
for(int i = 0; i < L.length; i++){
if(L.data[i] < s or L.data[i] > t){
L.data[j] = L.data[i];
}
}
L.length = j;
return true;
}
2.5
bool DeleteElem(SqList &L, int s, int t){
if(s > t || L.length == 0){
return false;
}
int j = 0;
for(int i = 0; i < L.length; i++){
if(L.data[i] < s or L.data[i] > t){
L.data[j] = L.data[i];
}
}
L.length = j;
return true;
}
2.6
void DeletesameNum(SqList &L){
int i, j;
for(i = 0, j = 1; j < L.length; j++){
if(L.data[i] != L.data[j]){
L.data[++i] = L.data[j];
}
L.length = i + 1;
}
}
2.7
bool combine(SqList L1, SqList L2, SqList &L3){
if(l1.length + L2.length > maxSize){
return false;
}
int i = 0, j = 0, k = 0;
while(i != L1.length && j != L2.length){
if(L1.data[i] < L.data[j]){
L3.data[k++] = L1.data[i++];
}
else{
L3.data[k++] = L2.data[j++];
}
}
while(i != L1.length){
L3.data[k++] = l1.data[i++];
}
while(j != L2.length){
L3.data[k++] = l2.data[j++];
}
L3.length = k;
return true;
}
2.8
typedef int DataType;
void reverse(DataType A[], int left, int right, arraySize){
if(left >= right || right >= arraySize){
return false;
}
int mid = (left + right) / 2;
for(int i = 0; i <= mid - left; i++){
DataType temp = A[left + i];
A[left + i] = A[right - i];
A[right - i] = temp;
}
}
void Exchange(DataType A[], int m, int n, int arraySize){
reverse(A, 0, m + n - 1, arraySize); // 整体逆置
reverse(A, 0, n - 1, arraySize); // 逆置b
reverse(A, n, m + n - 1, arraySize); // 逆置a
}
2.9
题目要求最少时间,使用折半查找
void Makex(ElemType A[], ElemType x){
int low = 0, high = n - 1, mid;
while(low <= high ){ //折半查找
mid = (low + high) / 2;
if(A[mid] == x){
break;
}
else if(A[mid] < x){
low = mid + 1;
}
else{
high = mid - 1;
}
}
// 两个if执行一个
if(A[mid] == x && mid != n - 1){ // 若最后一个元素等于x,则不存在交换
int t = A[mid];
A[mid] = A[mid + 1];
A[mid + 1] = t;
}
if(Low > high){
for(i = n - 1; i > high; i--){
A[i] = A[i - 1];
}
A[i] = x;
}
}
2.10
void Makex(ElemType A[], int n, int p){
reverse(A, 0, p - 1); // 前半部分(p)逆置
reverse(A, p, n - 1); // 后半部分( n - p)逆置
reverse(A, 0, n - 1); // 整体逆置
}
void reverse(ElemType A[], int left, int right){
int i, temp;
for(i = 0; i < (right - left + 1) / 2; i++){
temp = A[left + i];
A[left + i] = A[right - i];
A[right - i] = temp;
}
}
2.11
int search(int A[], int B[], int n){
int s1 = 0, d1 = n - 1, m1, s2 = 0, d2 = n - 1, m2; // 分别表示序列A和B的首位数、末尾数、中位数
while(s1 != d1 || s2 != d2){
m1 = (s1 + d1) / 2;
m2 = (s2 + d2) / 2;
if(A[m1] == B[m2]){ // 若a=b,则a或b是所求中位数
return A[m1];
}
if(A[m1] < B[m2]){ // 若a<b,则舍弃A中较小一半和B中较大一半
if((s1 + d1) % 2 == 0){ // 元素个数为奇数
s1 = m1; // 舍弃A中间点以前的部分
d2 = m2; // 舍弃B中间点以后的部分
}
else{ // 元素个数为偶数
s1 = m1 + 1; // 舍弃A中间点和中间点以前的部分
d2 = m2; // 舍弃B中间点以后的部分
}
}
else{ // 若a>b,则舍弃A中较大一半和B中较小一半
if((s2 + d2) % 2 == 0){ // 元素个数为奇数
d1 = m1; // 舍弃A中间点以后的部分
s2 = m2; // 舍弃B中间点以前的部分
}
else{ // 元素个数为偶数
d1 = m1; // 舍弃A中间点以后的部分
s2 = m2 + 1; // 舍弃B中间点和B中间点以前的部分
}
}
}
return A[s1] < B[s2] ? A[s1]:B[s2];
}
2.12
int search(int A[], int n){
int i, c, count = 1; // c用来保存候选主元素,count用来计数
c = A[0];
for(i = 1; i < n; i++){
if(A[i] == c){
count++; // 候选主元素计数
}
else{
if(count > 0){ // 处理不是候选主元素的情况
count--;
}
else{ // 更换候选主元素,重新计数
c = A[i];
count = 1;
}
}
}
if(count > 0){
for(i = count = 0; i < n; i++){ // 统计主元素出现次数
if(A[i] == c){
count++;
}
}
}
if(count > n / 2){
return c; // 确认候选主元素
}
else{
return -1; // 不存在主元素
}
}
2.13
int MinNum(int A[], int n){
int i, *B;
B = (int *)malloc(sizeof(int)*n);
memset(B, 0,sizeof(int)*n); // 赋初值为0
for(i = 0; i < n; i++){
if(A[i] > 0 && A[i] < n){
B[A[i] - 1] = 1;
}
}
for(i = 0; i < n; i++){
if(B[i] == 0){
break;
}
}
return i + 1;
}
2.14
#define Int_Max 0x7fffffff
int abs(int a){ // 计算绝对值
if(a < 0){
return -a;
}
else{
return a;
}
}
bool min(int a, int b, int c){ // a是否是三个数中最小值
if(a <= b && a <= c){
return true;
}
return false;
}
int findMin(int A[], int n, int B[], int m, int C[], int p){
int i = 0, j = 0, k = 0, D_min = Int_Max, D;
while(i < n && j < m && K < p && D_min > 0){
D = abs(A[i] - B[j]) + abs(B[j] - C[k]) + abs(C[k] - A[i]);
if(D < D_min){
D_min = D;
}
if(min(A[i], B[j], C[k])){
i++;
}
else if(min(B[j], C[k], A[i])){
j++;
}
else{
k++;
}
}
return D_min;
}
3、链表
3.1单链表
线性表的链式存储又称单链表。对于每个链表结点,除了存放元素自身信息之外,还要存放一个指向后继结点的指针。
单链表结点类型描述如下:
typedef struct LNode{
ElenType data; // 数据域
struct LNode *next; // 指针域
}LNode, *LinkList;
3.2 单链表基本操作实现
3.2.1 头插法
LinkList List_HeadInsert(LinkList &L){
LNode *s;
int x;
L = (LinkList)malloc(sizeof(LNode)); // 创建头结点
L->next = NULL; // 初始为空链表
scanf("%d", &x);
while(x != 9999){ // 输入9999表示结束
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
s->next = L->next;
L->next = s;
scanf("%d", &x);
}
return L;
}
3.2.2 尾插法
LinkList List_HeadInsert(LinkList &L){
int x;
L = (LinkList)malloc(sizeof(LNode)); // 创建头结点
LNode *s, *r = L; // r为尾指针
scanf("%d", &x);
while(x != 9999){ // 输入9999表示结束
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
r->next = s;
r = s;
scanf("%d", &x);
}
r->next = NULL; // 尾结点指针置空
return L;
}
3.2.3 按序号查找结点
LNode *GetElem(LinkList L, int i){
if(i < 1){
return NULL;
}
int j = 1;
LNode *p = L->next; // 第一个结点指针赋给p
while(p != NULL && j < i){
p = p->next; // 这里j小于i,但是p已经指向了下一结点,也就是第i个结点
j++;
}
return p;
}
3.2.4 按值查找结点
LNode *GetElem(LinkList L, ElemType e){
LNode *p = L->next; // 第一个结点指针赋给p
while(p != NULL && p->data != e){
p = p->next; // 这里j小于i,但是p已经指向了下一结点,也就是第i个结点
}
return p;
}
3.2.5 插入结点
p = GetElem(L, i - 1); // 查找插入位置的前驱结点
s->next = p->next;
p->next = s->next;
3.2.6 删除结点
p = GetElem(L, i - 1); // 查找删除位置的前驱结点
q = p->next;
p->next = q->next;
free(q);
3.3 双链表
typedef struct DNode{
ElemType data;
struct DNode *prior, *next;
}DNode, *DLinklist;
3.3.1 双链表插入结点
s->next = p->next;
p->next->prior = s;
s->prior = p;
p->next = s;
3.3.2 双链表删除结点
p->next = q->next;
q->next->prior = p;
free(q);
3.4 循环链表
3.4.1 循环单链表
3.4.2 循环双链表
4、课后大题
4.1
void Delx(LinkList &L, ElenType x){
LNode *p; // p指向删除结点
if(p == NULL){
return; // 递归出口
}
if(L->data == x){
p = L;
L = L->next;
free(p);
Delx(L, x);
}
else{
Delx(L->next, x); // 递归调用
}
}
4.2
void Delx(LinkList &L, ElenType x){
LNode *p = L->next, *pre = L, *q;
while(p != NULL){
if(p->data == x){
q = p;
p = p->next;
pre->next = p;
free(q);
}
else{
pre = p;
p = p->next;
}
}
}
4.3
void R_Print(LinkList L){
if(L->next != NULL){
R_Print(L->next);
}
if(L != NULL){
print(L->data);
}
}
void R_head(LinkList L){
if(L->next != NULL){
R_Print(L->next);
}
}
4.4
LinkList Del_Min(LinkList &L){
LNode *pre = L, *p = L->next, *min = L->next, *minpre = L;
while(p != NULL){
if(min->data > p->data){
min = p;
minpre = pre;
}
pre = p;
p = p->next;
}
minpre->next = min->next;
free(min);
return L;
}
4.5
LinkList Reverse 1(LinkList L){
LNode *p, *r;
p = L->next;
L->next = NULL;
while (p!=NULL) {
r = p->next;
p->next = L->next;
L->next = p;
p = r;
}
return L;
}
4.6
LinkList reverseInsert(LinkList &L){
LNode *p = L->next, *pre;
LNode *r = p->next;
p->next = NULL; // 构造只含一个数据结点的有序表
p = r;
while(p != NULL){
r = p->next; // 防断链
pre = L; // 每次都从头开始判断大小
while(pre->next != NULL && pre->next->data < p->data){
pre = pre->next; // 找到插入p的前驱结点pre
}
p->next = pre->next; // 将p插入pre后
pre->next = p;
p = r;
}
return L;
}
4.7
void delete(LinkList &L, int min, int max){
LNode *r = L, *p = L->next;
while (p != NULL){
if(p->data > min && p->data < max){
r->next = p->next;
free(p);
p = r->next;
}
else{
r = p;
p = p->next;
}
}
}