顺序表
顺序表代码
结构体定义
typedef struct {
ElemType *elem;
int length;
int listsize;
}SqList;
初始化顺序表
bool InitList_Sq(SqList &L) {
L.elem = (ElemType *)malloc(LIST_INIT_SIZE * sizeof(ElemType));
if (!L.elem) return false;
L.length = 0;
L.listsize = LIST_INIT_SIZE;
return true;
}
顺序表的插入
bool ListInsert_Sq(SqList &L, int i,ElemType e) {
if (i < 1 || i > L.length + 1) return false;
if (L.length >= L.listsize) {
ElemType *newbase = (ElemType *)realloc(L.elem, L.listsize * (L.listsize + LISTINCREMENT)*sizeof(ElemType));
if (!newbase) return false;
L.elem = newbase;
L.listsize += LISTINCREMENT;
}
ElemType * q = &L.elem[i - 1];
for (ElemType *p = &L.elem[L.length - 1];p >= q;--p) {*(p+1) = *p;}
*q = e;
++L.length;
return true;
}
顺序表的删除
bool ListDelete_Sq(SqList &L, int i,ElemType &e) {
if (i < 1 || i > L.length) return false;
ElemType * p = &(L.elem[i - 1]);
e = *p;
ElemType * q = &(L.elem[L.length - 1]);
for (++p;p <=q; ++p) *(p - 1) = *p;
--L.length;
return true;
}
查找指定元素在顺序表中的位置
int LocateElem_Sq(SqList L, ElemType e) {
for (int i = 1; i < L.length; ++i) {
if (L.elem[i-1] == e) return i;
else return -1;
}
}
有序表的合并(顺序表)
void MergeList_Sq(SqList &La, SqList &Lb,SqList &Lc) {
ElemType * pa = La.elem;
ElemType * pb = Lb.elem;
Lc.listsize = Lc.length = La.length + Lb.length;
ElemType * pc = Lc.elem = (ElemType *)malloc(Lc.listsize * sizeof(ElemType));
ElemType * pa_last = La.elem + La.length -1;
ElemType * pb_last = La.elem + La.length -1;
while (pa < pa_last && pb < pb_last) {
if (*pa <= *pb) *pc++ = *pa++;
else *pc++ = *pb++;
}
while (pa < pa_last) *pc++ = *pa++;
while (pb < pb_last) *pc++ = *pb++;
}
顺序表习题
从顺序表中删除最小值的元素(假设唯一),并返回被删除元素的值,空出的位置由最后一个元素填补。
void delete_Min(SqList &L,int &e) {
int i , min;
min = 0;
for(i = 1; i < L.length; ++i) {
if (L.elem[i] < L.elem[min]) min = i;
}
e = L.elem[min];
L.elem[min] = L.elem[L.length - 1];
L.length--;//这句话有争议,可写可不写,考试时建议两种都写
}
设计一个算法,江顺序表中的所有元素逆置,要求:算法只能使用1个元素分辅助空间。
void Reverse_List_Sq(SqList &L) {
int i ,temp;
for(i = 0;i < L.length / 2;++i) {
temp = L.elem[i];
L.elem[i] = L.elem[L.length - 1 - i];
L.elem[L.length - 1 - i] = temp;
}
}
对长度为n的顺序表L,编写一个时间复杂度为O(n),并只使用1个元素的辅助空间的算法,删除线性表中所有值为x的数据元素。
void Delete_x(SqList &L,int x) {
int i;
int count = 0;
for(i = 0;i < L.length; ++i) {
if (L.elem[i] != x) {
L.elem[count] = L.elem[i];
count++;
}
}
L.length = count;
}
从非空有序顺序表中删除所有其值重复的元素,使表中元素的值各不相同。
void DelSameElem(SqList &L) {
int i,k;
k = 1;
for(i = 1;i < L.length; ++i) {
if(L.elem[i-1] == L.elem[i] ) {
L.elem[k] = L.elem[i];
k++;
}
}
L.length = k;
}
线性表(a1,a2,…an)中的元素(整数)按值递增顺序存储。要求用最少时间在表中查找其值为x的元素。若找到,则将其与后继元素位置互换;若找不到,则将其插入表中,并使得表中元素仍然递增有序。
void LocateInsert(SqList &L,int x) {
int low = 0,high = L.length - 1,mid;
while(low <= high) {
mid = (low + high) / 2;
if(L.elem[mid] == x) break;
else if(L.elem[mid] < x) low = mid + 1;
else high = mid - 1;
}
if(L.elem[mid] == x && mid != L.length - 1) {
int temp = L.elem[mid];
L.elem[mid] = L.elem[mid + 1];
L.elem[mid + 1] = temp;
}
if(low > high) {
int i;
for(i = L.length - 1;i > high;i--) L.elem[i + 1] = L.elem[i];
L.elem[i + 1] = x;
L.length++;
}
}
从顺序表中删除所有其值在给定值s和t之间(包含s和t,要求s<t)的所有元素,若s或t不合理或顺序表为空,则显示出错信息并退出运行。
bool DeleteBetween(SqList &L, int s,int t) {
if(L.length == 0 || s >= t) return false;
int count = 0;
for (int i = 0; i < L.length; ++i) {
if(L.elem[i] < s && L.elem[i] > t) {
L.elem[count] = L.elem[i];
count++;
}
}
L.length = count;
return true;
}
已知在一个一位数组A[m+n]中依次存放两个线性表(a1,a2,a3,…,am)和(b1,b2,b3,…,bn)。编写一个函数,将数组中两个顺序表的位置互换,即将(b1,b2,b3,…,bn)放在(a1,a2,a3,…,am)前面。
void Reverse(int A[],int left,int right,int arraySize) {
if(left >= right || right >= arraySize) return;
int mid = left + (right - left) / 2;
for (int i = 0;i <= mid - left; i++) {
int temp = A[left+i];
A[left + i] = A[right - i];
A[right - i] = temp;
}
}
void Exchange(int A[],int m,int n,int arraySize) {
Reverse(A,0,m+n-1,arraySize);
Reverse(A,0,n-1,arraySize);
Reverse(A,n,m + n -1,arraySize);
}
链表
链表代码
结构体定义
typedef int ElemType;
typedef struct LNode {
int data;
struct LNode *next;
} LNode, *Linklist;
头插法创建链表
Linklist createLinkList_f(Linklist &L, int n) {
L = (Linklist)malloc(sizeof(LNode));
L->next = NULL;
for (int i = n; i > 0; i--) {
LNode *p = (LNode *)malloc(sizeof(LNode));
scanf("%d", &p->data);
p->next = L->next;
L->next = p;
}
return L; // 添加返回值
}
尾插法创建链表
Linklist createLinkList_r(Linklist &L, int n) {
L = (Linklist)malloc(sizeof(LNode));
L->next = NULL;
LNode* r = L;
for (int i = n; i > 0; i--) {
LNode *p = (LNode *)malloc(sizeof(LNode));
scanf("%d", &p->data);
p->next = r->next;
r->next = p;
r = p;
}
return L; // 添加返回值
}
判断链表是否为空
bool isEmpty(Linklist L) {
return L->next == NULL;
}
获取指定位置元素
bool GetElem(Linklist &L, int i, ElemType &e) {
LNode* p = L->next;
int j = 1;
while (p && j < i) {
p = p->next;
++j;
}
if (!p || j > i) return false;
e = p->data;
return true;
}
链表的插入
bool ListInsert(Linklist &L, int i, ElemType e) {
LNode* p = L;
int j = 0;
while (p && j < i - 1) {
p = p->next;
++j;
}
if (!p || j > i - 1) return false;
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
链表的删除
bool ListDelete(Linklist &L, int i, ElemType &e) {
LNode* p = L;
int j = 0;
while (p && j < i - 1) {
p = p->next;
++j;
}
if (!p || j > i - 1) return false;
LNode *q = p->next;
p->next = q->next;
e = q->data;
free(q);
return true;
}
有序表的合并(链表)
void MergeList(Linklist &La, Linklist &Lb, Linklist &Lc) {
LNode* pa = La->next;
LNode* pb = Lb->next;
LNode* pc;
Lc = pc = La;
while (pa && pb) {
if (pa->data < pb->data) {
pc->next = pa;
pc = pa;
pa = pa->next;
} else {
pc->next = pb;
pc = pb;
pb = pb->next;
}
}
pc->next = pa ? pa : pb; // 将最后未合并的部分连接
free(Lb);
}
链表习题
在带头结点的单链表L中,删除所有值为x的结点,并释放其空间,假设值为x的结点不唯一,试编写算法以实现上述操作。
void DeleteX(Linklist &L, ElemType x) {
LNode* p = L;
while (p->next) {
if (p->next->data == x) {
LNode* s = p->next;
p->next = p->next->next;
free(s);
} else {
p = p->next;
}
}
}
试编写在带头结点的单链表L中删除一个最小值结点的高效算法(假设该结点唯一)。
void DeleteMin(Linklist &L) {
if (!L || !L->next) return;
LNode* preMin = L;
LNode* minNode = L->next;
LNode* pre = L;
LNode* cur = L->next;
while (cur) {
if (cur->data < minNode->data) {
minNode = cur;
preMin = pre;
}
pre = cur;
cur = cur->next;
}
preMin->next = minNode->next;
free(minNode);
}
试编写算法将带头结点的单链表就地逆置,所谓“就地”是指辅助空间复杂度为O(1)。
Linklist Reverse(Linklist L) {
LNode * pre,*p = L->next,*r = p->next;
p->next = NULL;
while (r!=NULL) {
pre = p;
p = r;
r = r->next;
p->next = pre;
}
L->next = p;
return L;
}
设在一个代表头结点的单链表中,所有结点的元素值无序,试编写一个函数,删除表中所有介于给定的两个值(作为函数参数给出)之间的元素(若存在)。
void DeleteValBetween(Linklist &L,int l,int r) {
LNode* p = L;
if(l > r) {
int temp = l;
l = r;
r = temp;
}
while (p->next) {
if (p->next->data >= l && p->next->data <= r) {
LNode * q = p->next;
p->next = p->next->next;
free(q);
} else {
p = p->next;
}
}
}
设C={a1,b1,a2,b2,…,an.bn}为线性表,采用带头结点的单链表存放,设计一个就地算法,将其拆分为两个线性表,使得A={a1,a2…,an},B={BN,…,b2,b1}.
Linklist DisCreate_2(Linklist &A) {
Linklist B = (Linklist)malloc(sizeof(LNode));
B->next = NULL;
LNode *p = A->next,*q;
LNode *ra = A;
while (p!=NULL) {
ra->next = p; ra = p;
p = p->next;
if (p!=NULL) {
q = p->next;
q->next = B->next;
B->next = q;
p = q;
}
}
ra->next = NULL;
return B;
}
顺序栈
顺序栈代码
结构体定义
typedef int SElemType;
typedef struct {
SElemType *base;
SElemType *top;
int stacksize;
}SqStack;
初始化顺序栈
bool InitStack(SqStack &S) {
S.base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
if(!S.base) return false;
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
return true;
}
获取栈顶元素的两种写法
bool GetTop(SqStack &S, SElemType &e) {
if(S.top == S.base) return false;
e = *(S.top - 1);
return true;
}
SElemType GetTop(SqStack &S) {
if(S.top == S.base) return false;
return *(S.top - 1);
}
入栈
bool Push(SqStack &S, SElemType e) {
if(S.top - S.base >= S.stacksize) {
S.base = (SElemType *) realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(SElemType));
if(!S.base) return false;
S.top = S.base + S.stacksize;
S.stacksize += STACKINCREMENT;
}
*S.top++ = e;
return true;
}
出栈
bool Pop(SqStack &S, SElemType &e) {
if(S.top == S.base) return false;
e = *(--S.top);
}
判断栈是否为空
bool StackEmpty(SqStack &S) {
return S.top == S.base;
}
栈的应用
进制转换(以8为例)
void conversion() {
SqStack S;
int N,e;
InitStack(S);
scanf("%d", N);
while(N) {
Push(S,N % 8);
N /= 8;
}
while(!StackEmpty(S)) {
Pop(S,e);
printf("%d ",e);
}
}
括号匹配
bool BracketsCheck(char *str) {
SqStack S;
InitStack(S);
int i = 0;
int e;
while(str[i] != '\0') {
switch (str[i]) {
case '(': Push(S,'('); break;
case '{': Push(S,'{'); break;
case '[': Push(S,'['); break;
case ')': Pop(S,e);
if (e != ')') return false;
break;
case '}': Pop(S,e);
if (e != '}') return false;
break;
case ']': Pop(S,e);
if (e != ']') return false;
break;
}
i++;
}
if(!StackEmpty(S)) return false;
return true;
}
表达式求值
bool In(char c) {
switch(c) {
case '+':
case '-':
case '*':
case '/':
case '(':
case ')':
case '\n':return true;
default: return false;
}
}
char Precede(SElemType t1, SElemType t2)
{
// 根据教科书表3.1,判断t1,t2两符号的优先关系('#'用'\n'代替)
char f;
switch (t2)
{
case '+':
case '-':
if (t1 == '(' || t1 == '\n')
f = '<'; // t1 < t2
else
f = '>'; // t1 > t2
break;
case '*':
case '/':
if (t1 == '*' || t1 == '/' || t1 == ')')
f = '>'; // t1 > t2
else
f = '<'; // t1 < t2
break;
case '(':
if (t1 == ')')
{
printf("括号不匹配\n");
return false;
}
else
f = '<'; // t1 < t2
break;
case ')':
if (t1 == '(')
f = '='; // 匹配括号
else if (t1 == '\n')
{
printf("括号不匹配\n");
return false;
}
else
f = '>'; // t1 > t2
break;
case '\n': // '#'用'\n'代替
if (t1 == '\n')
f = '='; // t1 == t2
else
f = '>'; // t1 > t2
break;
default:
printf("无效的符号: %c\n", t2);
return false;;
}
return f;
}
SElemType Opreate(SElemType a, SElemType theta, SElemType b)
{
SElemType result;
switch (theta)
{
case '+':
result = a + b;
break;
case '-':
result = a - b;
break;
case '*':
result = a * b;
break;
case '/':
if (b == 0)
{
printf("除零错误\n");
return false;
}
result = a / b;
break;
default:
printf("无效操作符: %c\n", theta);
return false;
}
return result;
}
bool EvaluateExpression() {
SqStack OPTR,OPND;
InitStack(OPTR);Push(OPTR,'#');
InitStack(OPND);char c = getchar();
SElemType x,theta,a,b;
while(c != '#' ||GetTop(OPTR)!='#') {
if(!In(c)){Push(OPND,c);c = getchar();}
else
switch(Precede(GetTop(OPTR),c)) {
case '<':
Push(OPTR,c); c = getchar();
break;
case '='://拖括号并接收下一字符
Pop(OPTR,x);c = getchar();
break;
case '>':
Pop(OPTR,theta);
Pop(OPND,b);Pop(OPND,a);
Push(OPND,Opreate(a,theta,b));
break;
}
}
return GetTop(OPND);
}
队列
链队列
结构体定义
typedef int QElemType;
typedef struct QNode {
QElemType data;
struct QNode *next;
}QNode,* QueuePtr;
typedef struct {
QueuePtr front;
QueuePtr rear;
}LinkQueue;
初始化链队列
bool InitQueue(LinkQueue &Q) {
Q.front = Q.rear = (QueuePtr) malloc(sizeof(QNode));
if(!Q.front) return false;
Q.front->next = NULL;
return true;
}
销毁链队列
bool DestroyQueue(LinkQueue &Q) {
while(Q.front) {
Q.rear = Q.front->next;
free(Q.front);
Q.front = Q.rear;
}
return true;
}
入队(链队列)
bool EnQueue(LinkQueue &Q, QElemType e) {
QueuePtr p = (QueuePtr) malloc(sizeof(QNode));
if(!p) return false;
p->data = e;
p->next = NULL;
Q.rear->next = p;
Q.rear = p;
return true;
}
出队(链队列)
bool DeQueue(LinkQueue &Q, QElemType &e) {
if(Q.front == Q.rear) return false;
QueuePtr p = Q.front->next;
e = p->data;
Q.front->next = p->next;
if(Q.rear == p) Q.rear = Q.front;
free(p);
return true;
}
循环队列
结构体定义
#define MAXQSIZE 100
typedef int QElemType;
typedef struct {
QElemType *base;
int front;
int rear;
}SqQueue;
初始化
bool InitQueue(SqQueue &Q) {
Q.base = (QElemType *)malloc(MAXQSIZE * sizeof(QElemType));
if(!Q.base) return false;
Q.front = Q.rear = 0;
return true;
}
求队长
int QueueLength(SqQueue Q) {
return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
}
入队
bool EnQueue(SqQueue &Q, QElemType e) {
if((Q.rear + 1) % MAXQSIZE == Q.front) return false;
Q.base[Q.rear] = e;
Q.rear = (Q.rear + 1) % MAXQSIZE;
return true;
}
出队
bool DeQueue(SqQueue &Q, QElemType &e) {
if(Q.rear == Q.front) return false;
e = Q.base[Q.front];
Q.front = (Q.front + 1) % MAXQSIZE;
return true;
}
串
串的定长顺序存储
定义
#define MAXSTRLEN 255 //用户可在255以内定义最大串长
#include <cstdio>
typedef unsigned char SString[MAXSTRLEN + 1];
串连接(SString)
bool Concat(SString &T,SString S1,SString S2) {
if (S1[0] + S2[0] <= MAXSTRLEN) {
for (int i = 1; i <= S1[0]; i++) T[i] = S1[i];
for (int i = 1; i <=S2[0]; i++) T[S1[0] + i] = S2[i];
T[0] = S1[0] + S2[0];
return true;
}
else if (S1[0] < MAXSTRLEN) {
for (int i = 1; i <= S1[0]; i++) T[i] = S1[i];
for (int i = 1; S1[0] + i <= MAXSTRLEN; i++) T[S1[0] + i] = S2[i];
T[0] = MAXSTRLEN;
return true;
}
else {
for (int i = 0; i <= MAXSTRLEN; i++) T[i] = S1[i];
return true;
}
}
串的模式匹配
int Index(SString S,SString T,int pos) {
//返回字串T在主串S中第pos个字符之后的位置。若不存在,则函数值为0。
//其中,T非空,1<=pos<=StrLength(S)。
int i = pos; int j = 1;
while (i <= S[0] && j <= T[0]) {
if (S[i] == T[i]) { ++i; ++j;}
else {i = i - j + 2; j = 1;}
}
if (j > T[0]) return i - T[0];
else return 0;
}
串的堆分配存储
定义
typedef struct {
char *ch;
int length;
}HString;
串连接(HString)
bool Concat(HString &T,HString S1,HString S2) {
if(T.ch) free(T.ch);
if(!(T.ch = (char *)malloc((S1.length + S2.length) * sizeof(char)))) return false;
for(int i = 0; i < S1.length; i++) T.ch[i] = S1.ch[i];
T.length = S1.length + S2.length;
for (int i = S1.length; i < T.length; i++) T.ch[i] = S2.ch[i];
return true;
}
二叉树
定义
typedef int TElemType;
typedef struct BiTNode{
TElemType data;
struct BiTNode *lchild, *rchild;
}BiTNode,* BiTree;
创建二叉树
bool CreateBiTree(BiTree &T) {
int ch;
scanf("%d",&ch);
if(ch == '') T = NULL;
else {
if(!(T = (BiTNode *)malloc(sizeof(BiTNode)))) return false;
T->data = ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
return true;
}
先序遍历二叉树
void PreOreder(BiTree T) {
if (T) {
printf("%d",T->data);
PreOreder(T->lchild);
PreOreder(T->rchild);
}
}
中序非递归遍历二叉树
void InOrder_iter(BiTree BT) {
SqStack S;
InitStack(S);
Push(S,BT);
BiTNode * p;
p;
while(!StackEmpty(S)) {
while (GetTop(S,p) && p) Push(S,p->lchild);
Pop(S,p);
if(!StackEmpty(S)) {
Pop(S,p);
printf("%d ",p->data);
Push(S,p->rchild);
}
return;
}
}
求二叉树的深度(先序版)
int BiTreeDepth_f(BiTree T,int level,int &depth) {
//二叉树深度=叶子结点所在层次的最大值
if(T) {
if(level > depth) depth = level;
BiTreeDepth_f(T->lchild,level+1,depth);
BiTreeDepth_f(T->rchild,level+1,depth);
}
}
求二叉树的深度(后序版)
int BiTreeDepth_l(BiTree T) {
//二叉树的深度=MAX(左子树深度,右子树深度)+1。
int depth;
if(!T) depth = 0;
else {
int depthleft = BiTreeDepth_l(T->lchild);
int depthright = BiTreeDepth_l(T->rchild);
depth = std::max(depthleft,depthright) + 1;
}
return depth;
}
二分查找
int search(int A[], int e) {
int low = 0, high = e, mid;
while (low <= high) {
mid = (low + high) / 2;
if (A[mid] == e)
return mid;
else if (A[mid] < e)
low = mid + 1;
else
high = mid - 1;
}
return -1;
}
内部排序
直接插入排序
void InsertSort(SqList &L) {
int j;
for(int i = 2;i <= L.length;i++)
if(L.elem[i] < L.elem[i - 1]) {
L.elem[0] = L.elem[i];
L.elem[i] = L.elem[i - 1];
for (j = i - 2; L.elem[0] < L.elem[j]; j--)
L.elem[j + 1] = L.elem[j];
L.elem[j + 1] = L.elem[0];
}
}
折半插入排序
void BInsertSort(SqList &L) {
for (int i = 2; i < L.length; i++) {
L.elem[0] = L.elem[i];
int low = 1; int high = i - 1;
while (low <= high) {
int m = low + (high - low) / 2;
if (L.elem[0] < L.elem[m]) high = m - 1;
else low = m + 1;
}
for (int j = i - 1; j >= high + 1; j--) L.elem[j + 1] = L.elem[j];
L.elem[high + 1] = L.elem[0];
}
}
快速排序
int Partition(SqList &L, int low, int high) {
L.elem[0] = L.elem[low];
int pivotkey = L.elem[low];
while (low < high) {
while (low < high && L.elem[high] >= pivotkey) --high;
L.elem[low] = L.elem[high];
while (low < high && L.elem[low] <= pivotkey) ++low;
L.elem[high] = L.elem[low];
}
L.elem[low] = L.elem[0];
return low;
}
void QSort(SqList &L, int low, int high) {
if (low < high) {
int pivotloc = Partition(L, low, high);
QSort(L, low, pivotloc);
QSort(L, pivotloc + 1, high);
}
}
void QuickSort(SqList &L) {
QSort(L,1,L.length);
}
二路归并排序
void Merge(int SR[], int TR[], int s, int m, int t) {
int i = s, j = m + 1, k = s; // 定义两个子序列的起点和结果数组的起点
while (i <= m && j <= t) {
if (SR[i] <= SR[j]) {
TR[k++] = SR[i++];
} else {
TR[k++] = SR[j++];
}
}
while (i <= m) { // 将剩余部分复制到结果数组
TR[k++] = SR[i++];
}
while (j <= t) {
TR[k++] = SR[j++];
}
}
void MSort(int SR[],int TR1[],int s,int t) {
int * TR2;
if(s==t) TR1[s] = SR[s];
else {
int m = (s+t)/2;
MSort(SR,TR2,s,m);
MSort(SR,TR2,m+1,t);
Merge(TR2,TR1,s,m,t);
}
}
void MergeSort(SqList &L) {
MSort(L.elem,L.elem,1,L.length);
}