例题一:比较两个顺序表的大小
比较是通过由两个表的首数据一次向后遍历,逐个比较。如遇到A.elem[i] > B.elem[i],则A>B.如遇到A.elem[i] < B.elem[i]则B<A,若A.elem[i] = B.elem[i]则下一个数据继续比较。
#include<stdio.h>
#include<string.h>
const int LIST_INIT_SIZE = 100;
const int LISTINCREMENT = 10;
typedef struct {
char *elem;
int length;
int listsize;
int listincrementsize;
}SqList;
void InitList(SqList &L, int maxsize = LIST_INIT_SIZE, int incresize = LISTINCREMENT)
{
L.elem = new char[maxsize];
L.length = 0;
L.listsize = maxsize;
L.listincrementsize = incresize;
}
int compare(SqList A, SqList B)
{
int j = 0;
while (j < A.length&&j < B.length)
{
if (A.elem[j] < B.elem[j])
return (-1);
else if (A.elem[j] > B.elem[j])
return (1);
else j++;
}
if (A.length = B.length)
return(0);
else if (A.length < B.length)
return (-1);
else
return (1);
}
void main()
{
int i;
SqList A,B;
InitList(A);
InitList(B);
strcpy(A.elem, "abcdefegsgfd"); //对顺序表A进行赋值
A.length = 12;
strcpy(B.elem, "abcdfksdflpsf"); //对顺序表B进行赋值
B.length = 13;
i = compare(A, B);
if (i == 0)
printf("A和B相等。\n");
else if (i < 0)
printf("A小于B。\n");
else
printf("A大于B。\n");
}
定义两个顺序表,先定义顺序表数据结构,再定义顺序表变量,然后为其赋值时,可以循环赋值也可以用 strcpy() 函数直接赋值。对两个表进行比较时首先定义一个变量 j , 当 j 小于两个表的长度时循环,比较各个数据,若不同则返回相应的值,若相同则比较下一个数据。当跳出循环时,继续执行后续程序时,说明两表前面这部分数据相同,然后比较其表长。
总的来说就两步:一是 j 小于两表长度时比较单个数据大小,二是 j 超过某一个表长度时比较表长。
---------------------------------------------------------------------------------------------------------------------------------
例题二:利用尽量少的辅助空间,将顺序表前m个数据和后n个数据整体互换位置
算法一:利用辅助空间c,先将后n个数的第一个数提出放在c上,然后将前个数进行右移,再将c提前。首先定义两个循环变量i,j,然后大循环就是对于后m个数,for(j=0;j<m;j++); 先将A.elem[m+j]赋值给c,然后进入小循环,for(i=m+j ; i>j ; i--); 此处括号里的 i=m+j ;是因为最初 i 指向 c,但是由于后面的右移操作导致前m个数的下标会加一,所以要加上 j . 范围 i>j 的判断是因为小循环要执行m次,所以直接m+j-m得到 i>j. 最后一步是将c赋给前面的数,最初时A.elem[0],后面要加一所以是A.elem[j]; 代码如下:
#include<stdio.h>
#include<string.h>
const int LIST_INIT_SIZE = 100;
const int LISTINCREMENT = 10;
typedef struct {
char *elem;
int length;
int listsize;
int listincrementsize;
}SqList;
void InitList_Sq(SqList &L, int maxsize = LIST_INIT_SIZE, int incresize = LISTINCREMENT)
{
L.elem = new char[maxsize];
L.length = 0;
L.listsize = maxsize;
L.listincrementsize = incresize;
}
void exchange1(SqList &A, int m, int n)
{
int i, j; //定义i,j 用于循环分别表示前m个数据和后n个数据
char c; //辅助空间
for (j = 0; j < n; j++) //对后n个数据循环
{
c = A.elem[m + j]; //将后n个数据的第一个数据拿出来 即A.elem[m+j];
for (i = m + j; i > j; i--) //对前m个数据进行循环右移
A.elem[i] = A.elem[i - 1];
A.elem[j] = c; //再将之前提出的数放在前面的位置
}
}
void main()
{
int i;
SqList A;
InitList_Sq(A);
strcpy(A.elem, "abcdefghijklmn");
A.length = 14;
exchange1(A, 7, 7);
for (i = 0; i < 14; i++)
printf("%c ", A.elem[i]);
}
算法二:构造辅助函数void invert(char R[], int s, int t),功能是实现数组R[s]到R[t]之间数据的逆置。则调用该函数三次,先整体逆置,再将前n个逆置,最后将后m个逆置即可。对于逆置函数,定义辅助空间和循环变量,然后循环,for (i = s; i <= (s + t) / 2; i++) 其中 i 初始值指向R[s], 由于共有s+t个数 所以循环 i<=(s+t)/2 次,互换时 R[t + s - i],是因为此处原本是R[t],但是由于后面循环要减一,所以要减去i,为保证下标不变所以加上s。代码如下:
#include<stdio.h>
#include<string.h>
const int LIST_INIT_SIZE = 100;
const int LISTINCREMENT = 10;
typedef struct {
char *elem;
int length;
int listsize;
int listincrementsize;
}SqList;
void InitList_Sq(SqList &L, int maxsize = LIST_INIT_SIZE, int incresize = LISTINCREMENT)
{
L.elem = new char[maxsize];
L.length = 0;
L.listsize = maxsize;
L.listincrementsize = incresize;
}
void invert(char R[], int s, int t)
{
char c;
int i;
for (i = s; i <= (s + t) / 2; i++)
{
c = R[i];
R[i] = R[t + s - i]; //此处原本是R[t],但是由于后面循环要减一,所以要减去i,为保证下标不变所以加上s
R[t + s - i] = c;
}
}
void exchange2(SqList A, int m, int n)
{
invert(A.elem, 0, m + n - 1);
invert(A.elem, 0, n - 1);
invert(A.elem, n, m + n - 1);
}
void main()
{
int i;
SqList A;
InitList_Sq(A);
strcpy(A.elem, "abcdefghijklmn");
A.length = 14;
exchange2(A, 7, 7);
for (i = 0; i < 14; i++)
printf("%c ", A.elem[i]);
}
-------------------------------------------------------------------------------------------------------------------
例题三:含有相同元素的表B,构造表A,使其只有B中不相同的元素
本题建立一条空的A表用于存储B表中的数据,在函数体中,首先定义两个循环变量 i, j,分别对应表B和表A,再定义辅助空间e存放数据。先将B表中首数据赋值给A.elem[0],然后进入大循环,for (i = 1; i < B.length; i++)在B表中从第二个元素开始进行遍历,将B表中的数据放在e中,然后对 j 清零,进入小循环while (j < A.length&&A.elem[j] != e)开始对A表进行遍历 j++.当跳出循环时判断是 j=A.length还是A.elem[j]==e.然后选择是将e插入到A表的末尾还是直接进入下一次大循环。
#include<stdio.h>
#include<string.h>
const int LIST_INIT_SIZE = 100;
const int LISTINCREMENT = 10;
typedef struct {
char *elem;
int length;
int listsize;
int listincrementsize;
}SqList;
void InitList_Sq(SqList &L, int maxsize = LIST_INIT_SIZE, int incresize = LISTINCREMENT)
{
L.elem = new char[maxsize];
L.length = 0;
L.listsize = maxsize;
L.listincrementsize = incresize;
}
void purge_Sq(SqList &A, SqList &B)
{
int i, j; //i,j 分别对应检索表B和表A
char e;
A.elem[0] = B.elem[0];
A.length = 1;
for (i = 1; i < B.length; i++)
{
e = B.elem[i];
j = 0; //对A表检索时先将J清零
while (j < A.length&&A.elem[j] != e)
j++;
if (j == A.length)
{
A.elem[A.length] = e;
A.length++;
}
}
delete[] B.elem;
B.listsize = 0;
}
void main()
{
int i;
SqList A;
SqList B;
InitList_Sq(B);
InitList_Sq(A);
strcpy(B.elem, "abbbcdeeefggghijjjklmn");
B.length = 22;
printf("处理前B表的数据为:");
for (i = 0; i < B.length; i++)
printf("%c ", B.elem[i]);
printf("\n");
purge_Sq(A, B);
printf("处理后把B表的数据赋给A表,为:");
for (i = 0; i < A.length; i++)
printf("%c ", A.elem[i]);
}
本笔记所依据的教材为严薇敏版的《数据结构及应用算法教程》
所有代码在Visual Studio 2017上均可正常运行
如有错误欢迎指出