文章目录
第二章
顺序表的操作
#define MAXSIZE 100//存储空间初始分配量
typedef struct{
ElemType *elem;
int length;
int listsize;
}SqList;
void InitList_Sq(SqList &L)//初始化
{
L.elem = new ElemType[MaxSIZE];
if(!L.elem)
return;
L.length = 0;
}
int LocateElem(SqList L,ElemType e)//查找
{
for(int i = 0; i < L.length; i++)
{
if(L.elem[i] == e)
return i + 1;
}
return 0;
}
void ListInsert(SqList &L, int i, ElemType e)//插入e
{
if((i < 1) || (i > L.length + 1) || (L.length == MAXSIZE))
return;//i值不合法,当前存储空间已满
for(int j = L.length - 1; j >= i -1; j--)
{
L.elem[j + 1] = L.elem[j];
}
L.elem[i - 1] = e;
++L.length;
}
void ListDelete(SqList &L, int i)//删除
{
for(int j = i; j <= L.length - 1; j++)
{
L.elem[j - 1] = L.elem[j];
}
--L.length;
}
void GetElem(SqList L, int i, ElemType &e)//取第i个元素的值
{
if((i < 1) || (i > L.length))
return;
e = L.elem[i - 1];
}
单链表的操作
#define MAXSIZE 100//存储空间初始分配量
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;
void InitList(LinkList &L)//初始化
{
L = new LNode;
L -> next = NULL;
}
void GetElem(LinkList L, int i, ElemType &e)//取第i个元素的值
{
LinkList *p;
p = L -> next;//p = (*l).next;
j = 1;
while(p && j < i)
{
p = p -> next;
++j;
}
if(!p || j > i)
return ERROR;
e = p -> data;
}
LNode *LocateElem(LinkList L,ElemType e)//查找
{
p = L -> next;
while(p && p -> data != e)
{
p = p -> next;
}
return p;
}
void ListInsert(LinkList &L, int i, ElemType e)//插入e
{
p = L;
j = 0;
while(p && (j < i -1))
{
p = p -> next;
++j;
}
if(!p || j > i - 1)
return ERROR;
s = new LNode;
s -> data = e;
s -> next = p -> next;
p -> next = s;
}
void ListDelete(LinkList &L, int i)//删除
{
p = L;
j = 0;
while((p -> next) && (j < i - 1))
{
p = p -> next;
++j;
}
if(!(p -> next) || (j > i - 1))
return ERROR;
q = p -> next;
p -> next = q -> next;
delete q;
}
void CreatList_H(LinkList &L, int n)
{
L = new LNode;
L -> next = NULL;
for(i = 0; i < n; ++i)
{
p = new LNode;
cin>>p -> data;
p -> next = L -> next;
L -> next = p;
}
}
void CreatList_R(LinkList &L, int n)
{
L = new LNode;
L -> next = NULL;
r = L;
for(i = 0; i < n; ++i)
{
p = new LNode;
cin>>p -> data;
p -> next = NULL;
r -> next = p;
r = p;
}
}
int main()
{
LinkList *h;
ElemType e,ch;
InitList(h);
int i=1;
while((ch=getchar())!='\n')
{
ListInsert(h,i,ch);
i++;
}
DispList(h);
scanf("\n%d",&i);
if(ListDelete(h,i,e))
printf("delete %dth: %c\n",i,e);
else
printf("delete failed!\n");
DispList(h);
DestroyList(h);
return 0;
}
线性表合并
void MergeList_Sq(SqList LA, SqList LB, SqList &LC)
{
LC.length = LA.length + LB.length;
LC.elem = new ElemType[LC.length];
pc = LC.elem;
pa = LA.elem;
pb = LB.elem;
pa_last = LA.elme + LA.length - 1;
pb_last = LB.elem + LB.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++;
}
顺序表合并
#include<bits/stdc++.h>
using namespace std;
typedef int ElemType;
typedef struct LNode
{
ElemType data;
struct LNode *next;
} LNode,*LinkList;
void Create(LinkList &L)
{
LNode *p = L;
int n;
while((p->next) != NULL)
{
p = p->next;
}
cin>>n;
while(n != -1)
{
LNode *tmp = (LNode*)malloc(sizeof(LNode));
tmp -> data = n;
p -> next = tmp;
tmp -> next = NULL;
cin>>n;
p = p -> next;
}
}
void Combine(LinkList &s1,LinkList &s2,LinkList &s3)
{
LNode *l1, *l2, *l3;
l1 = s1 -> next;
l2 = s2 -> next;
l3 = s3;
while(l1 && l2)
{
if(l1 -> data <= l2 -> data)
{
l3 -> next = l1;
l1 = l1 -> next;
}
else
{
l3 -> next = l2;
l2 = l2 -> next;
}
l3 = l3 -> next;
}
l3 -> next = l1 ? l1 : l2;
s1 -> next = NULL;
s2 -> next = NULL;
}
void Print(LinkList &L)
{
LNode *p = L -> next;
if(p == NULL)
cout<<"NULL";
while(p != NULL)
{
if(p -> next != NULL)
cout<<p -> data<<" ";
else
cout<<p -> data;
p = p->next;
}
}
int main()
{
LinkList S1, S2, S3;
S1 = (LinkList)malloc(sizeof(LNode));
S1 -> next = NULL;
S2 =(LinkList)malloc(sizeof(LNode));
S2 -> next = NULL;
S3 = (LinkList)malloc(sizeof(LNode));
S3 -> next = NULL;
Create(S1);
Create(S2);
Combine(S1, S2, S3);
Print(S3);
return 0;
}
两个有序链表序列的交集
#include<bits/stdc++.h>
using namespace std;
typedef int ElemType;
typedef struct LNode
{
ElemType data;
struct LNode *next;
} LNode,*LinkList;
void Create(LinkList &L)
{
LNode *p = L;
int n;
while((p->next) != NULL)
{
p = p->next;
}
cin>>n;
while(n != -1)
{
LNode *tmp = (LNode*)malloc(sizeof(LNode));
tmp -> data = n;
p -> next = tmp;
tmp -> next = NULL;
cin>>n;
p = p -> next;
}
}
void Union(LinkList s1,LinkList s2,LinkList &s3)
{
LNode *l1, *l2, *tmp, *cur = s3;
l1 = s1 -> next;
l2 = s2 -> next;
while(l1&&l2)
{
if(l1 -> data < l2 -> data)
{
l1 = l1 -> next;
}
else if(l1 -> data > l2 -> data)
{
l2 = l2 -> next;
}
else
{
tmp = (LNode*)malloc(sizeof(LNode));
tmp -> data = l1 -> data;
tmp -> next = NULL;
cur -> next = tmp;
cur = tmp;
l1 = l1 -> next;
l2 = l2 -> next;
}
}
}
void Print(LinkList &L)
{
LNode *p = L -> next;
if(p == NULL)
cout<<"NULL";
while(p != NULL)
{
if(p -> next != NULL)
cout<<p -> data<<" ";
else
cout<<p -> data;
p = p->next;
}
}
int main()
{
LinkList S1, S2, S3;
S1 = (LinkList)malloc(sizeof(LNode));
S1 -> next = NULL;
S2 =(LinkList)malloc(sizeof(LNode));
S2 -> next = NULL;
S3 = (LinkList)malloc(sizeof(LNode));
S3 -> next = NULL;
Create(S1);
Create(S2);
Union(S1, S2, S3);
Print(S3);
return 0;
}
(4)递增排列两个集合A和B 的差集
- (即仅由在A中出现而不在B中出现的元素所构成的集合),并以同样的形式存储,同时返回该集合的元素个数。
- [题目分析]
求两个集合A和B的差集是指在A中删除A和B中共有的元素,即删除链表中的相应结点,所以要保存待删除结点的前驱,使用指针pre指向前驱结点。pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点,从第一个结点开始进行比较,当两个链表La和Lb均为到达表尾结点时,如果La表中的元素小于Lb表中的元素,pre置为La表的工作指针pa删除Lb表中的元素;如果其中一个表中的元素较小时,删除此表中较小的元素,此表的工作指针后移。当链表La和Lb有一个为空时,依次删除另一个非空表中的所有元素。
void Difference(LinkList& La, LinkList& Lb,int *n)
{//差集的结果存储于单链表La中,*n是结果集合中元素个数,调用时为0
pa=La->next; pb=Lb->next;//pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点
pre=La;//pre为La中pa所指结点的前驱结点的指针
while(pa&&pb)
{
if(pa->data<q->data)
{
pre=pa;
pa=pa->next;
*n++;
}//A链表中当前结点指针后移
else if(pa->data>q->data)
q=q->next;//B链表中当前结点指针后移
else
{
pre->next=pa->next;//处理A,B中元素值相同的结点,应删除
u=pa;
pa=pa->next;
delete u;//删除结点
}
}
}
将两个递增的有序链表合并为一个递增的有序链表
-
要求结果链表仍使用原来两个链表的存储空间, 不另外占用其它的存储空间。表中不允许有重复的数据
-
分析
合并后的新表使用头指针Lc指向,pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点,从第一个结点开始进行比较,当两个链表La和Lb均为到达表尾结点时,依次摘取其中较小者重新链接在Lc表的最后。如果两个表中的元素相等,只摘取La表中的元素,删除Lb表中的元素,这样确保合并后表中无重复的元素。当一个表到达表尾结点,为空时,将非空表的剩余元素直接链接在Lc表的最后。
void MergeList(LinkList &La,LinkList &Lb,LinkList &Lc)
{//合并链表La和Lb,合并后的新表使用头指针Lc指向
pa=La->next; pb=Lb->next;
//pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点
Lc=pc=La; //用La的头结点作为Lc的头结点
while(pa && pb)
{if(pa->data<pb->data){pc->next=pa;pc=pa;pa=pa->next;}
//取较小者La中的元素,将pa链接在pc的后面,pa指针后移
else if(pa->data>pb->data) {pc->next=pb; pc=pb; pb=pb->next;}
//取较小者Lb中的元素,将pb链接在pc的后面,pb指针后移
else //相等时取La中的元素,删除Lb中的元素
{pc->next=pa;pc=pa;pa=pa->next;
q=pb->next;delete pb ;pb =q;
}
}
pc->next=pa?pa:pb; //插入剩余段
delete Lb; //释放Lb的头结点
}
通过一趟遍历在单链表中确定值最大的结点
- [题目分析]
假定第一个结点中数据具有最大值,依次与下一个元素比较,若其小于下一个元素,则设其下一个元素为最大值,反复进行比较,直到遍历完该链表。
ElemType Max (LinkList L ){
if(L->next==NULL) return NULL;
pmax=L->next; //假定第一个结点中数据具有最大值
p=L->next->next;
while(p != NULL ){//如果下一个结点存在
if(p->data > pmax->data) pmax=p;//如果p的值大于pmax的值,则重新赋值
p=p->next;//遍历链表
}
return pmax->data;
通过遍历一趟,将链表中所有结点的链接方向逆转,仍利用原表的存储空间。
- [题目分析]
从首元结点开始,逐个地把链表L的当前结点p插入新的链表头部。
void inverse(LinkList &L)
{// 逆置带头结点的单链表 L
p=L->next; L->next=NULL;
while ( p) {
q=p->next; // q指向*p的后继
p->next=L->next;
L->next=p; // *p插入在头结点之后
p = q;
}
}
第三章
双栈结构
-
将编号为0和1的两个栈存放于一个数组空间V[m]中,栈底分别处于数组的两端。当第0号栈的栈顶指针top[0]等于-1时该栈为空,当第1号栈的栈顶指针top[1]等于m时该栈为空。两个栈均从两端向中间增长。试编写双栈初始化,判断栈空、栈满、进栈和出栈等算法的函数。双栈数据结构的定义如下:
Typedef struct
{int top[2],bot[2]; //栈顶和栈底指针
SElemType *V; //栈数组
int m; //栈最大可容纳元素个数
}DblStack
-
[题目分析]
两栈共享向量空间,将两栈栈底设在向量两端,初始时,左栈顶指针为-1,右栈顶为m。两栈顶指针相邻时为栈满。两栈顶相向、迎面增长,栈顶指针指向栈顶元素。 -
算法讨论]
请注意算法中两栈入栈和退栈时的栈顶指针的计算。左栈是通常意义下的栈,而右栈入栈操作时,其栈顶指针左移(减1),退栈时,栈顶指针右移(加1)。
int Init()//初始化
{
S.top[0]=-1;
S.top[1]=m;
return 1; //初始化成功
}
int push(stk S,int i,int x) //入栈操作,i为栈号,i=0表示左栈,i=1为右栈,x是入栈元素。入栈成功返回1,失败返回0
{
if(i<0||i>1)
{
cout<<“栈号输入不对”<<endl;
exit(0);
}
if(S.top[1]-S.top[0]==1)
{
cout<<“栈已满”<<endl;
return(0);
}
switch(i)
{
case 0:
S.V[++S.top[0]]=x;
return(1);
break;
case 1:
S.V[--S.top[1]]=x;
return(1);
}
}//push
ElemType pop(stk S,int i)//退栈。i代表栈号,i=0时为左栈,i=1时为右栈。退栈成功时返回退栈元素
{
if(i<0 || i>1)
{
cout<<“栈号输入错误”<<endl;
exit(0);
}
switch(i)
{
case 0:
if(S.top[0]==-1)
{
cout<<"栈空"<<endl;
return -1;
}
else return(S.V[S.top[0]--]);
case 1:
if(S.top[1]==m)
{
cout<<“栈空”<<endl;
return(-1);
}
else
return(S.V[S.top[1]++]);
}
}
int Empty()
{
return (S.top[0]==-1 && S.top[1]==m);
}
回文
- 回文是指正读反读均相同的字符序列,如“abba”和“abdba”均是回文,但“good”不是回文。试写一个算法判定给定的字符向量是否为回文。(提示:将一半字符入栈)
- [题目分析]
将字符串前一半入栈,然后,栈中元素和字符串后一半进行比较。即将第一个出栈元素和后一半串中第一个字符比较,若相等,则再出栈一个元素与后一个字符比较,……,直至栈空,结论为字符序列是回文。在出栈元素与串中字符比较不等时,结论字符序列不是回文。
#define StackSize 100 //假定预分配的栈空间最多为100个元素
typedef char DataType;//假定栈元素的数据类型为字符
typedef struct
{
DataType data[StackSize];
int top;
} SeqStack;
int IsHuiwen( char *t)
{
//判断t字符向量是否为回文,若是,返回1,否则返回0
SeqStack s;
int i, len;
char temp;
InitStack( &s);
len=strlen(t); //求向量长度
for ( i=0; i<len/2; i++)//将一半字符入栈
Push( &s, t[i]);
while( !EmptyStack( &s))
{
// 每弹出一个字符与相应字符比较
temp=Pop (&s);
if( temp!=S[i]) return 0 ;// 不等则返回0
else i++;
}
return 1 ; // 比较完毕均相等则返回 1
}
第五章
二叉树四种遍历
//二叉树四种遍历
void InorderTraversal( BinTree BT )
{
if(BT)
{
InorderTraversal(BT -> Left);
printf(" %c", BT -> Data);
InorderTraversal(BT -> Right);
}
}
void PreorderTraversal( BinTree BT )
{
if(BT)
{
printf(" %c", BT -> Data);
PreorderTraversal(BT -> Left);
PreorderTraversal(BT -> Right);
}
}
void PostorderTraversal( BinTree BT )
{
if(BT)
{
PostorderTraversal(BT -> Left);
PostorderTraversal(BT -> Right);
printf(" %c", BT -> Data);
}
}
void LevelorderTraversal( BinTree BT )
{
BinTree p;
BinTree q[100];
int flag = 0, i = 0;
if(BT)
{
q[i++] = BT;
while(flag != i)
{
p = q[flag++];
printf(" %c", p -> Data);
if(p -> Left != NULL)
{
q[i++] = p -> Left;
}
if(p -> Right != NULL)
{
q[i++] = p -> Right;
}
}
}
}
先序遍历的顺序建立二叉链表
void CreatBiTree(BiTree &T)
{
cin>>ch;
if(ch == '#')
T = NULL;//递归结束,建空树
else
{
T = new BiTNode;
T -> data = ch;
CreatBiTree(T -> lchild);
CreatBiTree(T -> rchild);
}
}
计算二叉树深度
int Depth(BiTree T)
{
if(T = NULL)
return 0;
else
{
m = Depth(T -> lchild);
n = Depth(T -> rchild);
if(m > n)
return m + 1;
else
return n + 1;
}
}
二叉树最大的宽度
- 二叉树的最大宽度是指二叉树所有层中结点个数的最大值
- [题目分析] 求最大宽度可采用层次遍历的方法,记下各层结点数,每层遍历完毕,若结点数大于原先最大宽度,则修改最大宽度。
int Width(BiTree bt)//求二叉树bt的最大宽度
{
if (bt==null) return (0); //空二叉树宽度为0
else
{
BiTree Q[]; //Q是队列,元素为二叉树结点指针,容量足够大
front=1;
rear=1;
last=1;
//front队头指针,rear队尾指针,last同层最右结点在队列中的位置
temp=0;
maxw=0; //temp记局部宽度, maxw记最大宽度
Q[rear]=bt; //根结点入队列
while(front<=last)
{
p=Q[front++];
temp++; //同层元素数加1
if (p->lchild!=null) Q[++rear]=p->lchild; //左子女入队
if (p->rchild!=null) Q[++rear]=p->rchild; //右子女入队
if (front>last) //一层结束,
{
last=rear;
if(temp>maxw)
maxw=temp;//last指向下层最右元素, 更新当前最大宽度
temp=0;
}
}
return (maxw);
}
根据后序和中序遍历输出先序遍历
#include<bits/stdc++.h>
using namespace std;
int in[101],post[101];
typedef struct BiTNode{
int data;
struct BiTNode *lchild;
struct BiTNode *rchild;
}BiTNode,*BiTree;
BiTree Build(int *in,int *post,int n)
{
if(n <= 0)
return NULL;
int *p = in;
while(p){
if(*p == *(post + n - 1))
break;
p++;
}
BiTree T = new BiTNode;
T -> data = *p;
int len = p - in;
T -> lchild = Build(in, post, len);
T -> rchild = Build(p + 1, post + len, n - len - 1);
return T;
}
void PreorderPrintLeaves(BiTree T)
{
if(T){
printf(" %d",T -> data);
PreorderPrintLeaves(T->lchild);
PreorderPrintLeaves(T->rchild);
}
return;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n, i;
BiTree T;
cin>>n;
for(i = 0;i < n;i++)
scanf("%d",&post[i]);
for(i = 0;i < n;i++)
scanf("%d",&in[i]);
T = Build(in,post,n);
printf("Preorder:");
PreorderPrintLeaves(T);
return 0;
}
家谱处理
#include <bits/stdc++.h>
using namespace std;
int main()
{
vector<string> name(101);
map<string, string> father;
int n, m;
scanf("%d %d", &n, &m);
getchar();
while(n--)
{
string str;
getline(cin, str);
int cnt = count(str.begin(), str.end(), ' ');
if(cnt == 0)
{
father[str] = "root";
name[0] = str;
}
else
{
str = str.substr(cnt);
father[str] = name[cnt / 2 - 1];
name[cnt / 2] = str;
}
}
while(m--)
{
string a, b, c, d;
cin >> a >> b >> b >> c >> b >> d;
switch(c[0])
{
case 'p':
swap(a, d);
case 'c':
if(father[a] == d)
printf("True\n");
else
printf("False\n");
break;
case 's':
if(father[a] == father[d])
printf("True\n");
else
printf("False\n");
break;
case 'a':
swap(a, d);
case 'd':
while(father[a] != d && father[a] != "root")
a = father[a];
if(father[a] == "root")
printf("False\n");
else
printf("True\n");
}
}
return 0;
}
修理牧场
#include <bits/stdc++.h>
using namespace std;
int main()
{
priority_queue<int,vector<int>,greater<int> >l;
int n, data, i;
cin>>n;
for(i = 0; i < n; i++)
{
cin>>data;
l.push(data);
}
int sum = 0;
while(l.size() != 1)
{
int x = l.top();
l.pop();
int y = l.top();
l.pop();
sum += x + y;
l.push(x + y);
}
printf("%d\n", sum);
return 0;
}
第八章
希尔排序
void ShellSort(SqList &L,int dlta[ ],int t){
//按增量序列dlta[0…t-1]对顺序表L作Shell排序
for(k=0;k<t;++k)
ShellInsert(L,dlta[k]);
//增量为dlta[k]的一趟插入排序
} // ShellSort
void ShellInsert(SqList &L,int dk)
{
for(i=dk+1;i<=L.length; ++ i)
if(r[i].key < r[i-dk].key)
{
r[0]=r[i];
for(j=i-dk; j>0 &&(r[0].key<r[j].key); j=j-dk)
r[j+dk]=r[j];
r[j+dk]=r[0];
}
}
冒泡排序
void main()
{ int a[11]; /*a[0]不用,之用a[1]~a[10]*/
int i,j,t;
printf("\nInput 10 numbers: \n");
for(i=1;i<=10;i++) scanf("%d",&a[i]); printf("\n");
for(j=1;j<=9;j++)
for(i=1;i<=10-j;i++)
if(a[i]>a[i+1]) {t=a[i];a[i]=a[i+1];a[i+1]=t;}//交换
for(i=1;i<=10;i++) printf("%d ",a[i]);
}
选择排序
void SelectSort(SqList &K)
{
for (i=1; i<L.length; ++i)
{ //在L.r[i..L.length] 中选择key最小的记录
k=i;
for( j=i+1;j<=L.length ; j++)
if ( L.r[j].key <L.r[k].key) k=j;
if(k!=i)L.r[i]←→L.r[k];
}
}
快速排序
func Quick2Sort(values []int) {
if len(values) <= 1 {
return
}
mid, i := values[0], 1
head, tail := 0, len(values)-1
for head < tail {
fmt.Println(values)
if values[i] > mid {
values[i], values[tail] = values[tail], values[i]
tail--
} else {
values[i], values[head] = values[head], values[i]
head++
i++
}
}
values[head] = mid
Quick2Sort(values[:head])
Quick2Sort(values[head+1:])
}