大二学生的 C++数据结构 有部分Openjudge提交的代码没有删除
邮箱:liu_772021@yeah.net
欢迎交流讨论~
有用的话,点赞留言就可以表示感谢啦
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
typedef int ElemType;
#define MAX_SIZE 100
#define INF 10000000
//单链表结点类型
typedef struct node{
//数据域
ElemType data;
//指针域
struct node *next;
} SLinkNode;
//顺序表类型
typedef struct{
ElemType data[MAX_SIZE];
int length;
}SqList;
//初始化单链表L
void InitList(SLinkNode *&L){
//创建头结点L
L=(SLinkNode *)malloc(sizeof(SLinkNode));
L->next=NULL;
}
//判断单链表是否为空
void isBlank(SLinkNode*&L){
if(L->next==L)
cout<<"yes";
else
cout<<"no";
cout<<endl;
}
//销毁单链表L
void DestroyList(SLinkNode *&L){
SLinkNode *pre = L, *p = pre->next;
while (p!=NULL){
free(pre);
//pre、p同步后移
pre=p; p=p->next;
}
free(pre);
}
//求长度
int GetLength(SLinkNode *L){
int i=0;
SLinkNode *p=L->next;
while (p!=NULL){
i++;
p=p->next;
}
return i;
}
//求第i个结点值
int GetElem(SLinkNode *L,int i,ElemType &e){
int j=0;
//p指向头结点,计数器j置为0
SLinkNode *p=L;
//参数i错误返回0
if (i<=0){
return 0;
}
while (p!=NULL && j<i){
j++;
p=p->next;
}
//未找到返回0
if (p==NULL){
return 0;
}
//找到后返回1
else{
e=p->data;
return 1;
}
}
//求第一个值为e的结点位置
int Locate(SLinkNode *L,ElemType e){
SLinkNode *p=L->next;
//p指向第一个数据结点,j置为其序号1
int j=1;
while (p!=NULL && p->data!=e){
p=p->next;
j++;
}
//未找到返回0
if (p==NULL) return(0);
//找到后返回其序号
else return(j);
}
//插入结点值为x的结点
int InsElem(SLinkNode *&L,ElemType x,int i){
int j=0;
SLinkNode *p=L,*s;
//参数i错误返回0
if (i<=0){
return 0;
}
//查找第i-1个结点p
while (p!=NULL && j<i-1){
j++;
p=p->next;
}
//未找到第i-1个结点时返回0
if (p==NULL){
return 0;
}
//找到第i-1个结点p
else{
s=(SLinkNode *)malloc(sizeof(SLinkNode));
//创建存放元素x的新结点s
s->data=x;
//将s结点插入到p结点之后
s->next=p->next;
p->next=s;
//插入运算成功,返回1
return 1;
}
}
//删除结点
int DelElem(SLinkNode *&L,int i){
int j=0;
SLinkNode *p=L,*q;
//参数i错误返回0
if (i<=0){
return 0;
}
//查找第i-1个结点
while (p!=NULL && j<i-1){
j++;
p=p->next;
}
//未找到第i-1个结点时返回0
if (p==NULL)
return 0;
//找到第i-1个结点p
else{
//q指向被删结点
q=p->next;
//没有第i个结点时返回0
if (q==NULL)
return 0;
else{
//从单链表中删除q结点
p->next=q->next;
//释放其空间
free(q);
return 1;
}
}
}
//输出单链表
void DispList(SLinkNode *L){
SLinkNode *p=L->next;
while (p!=NULL)
{ printf("%d ",p->data);
p=p->next;
}
printf("\n");
}
//头插法建表
void CreateListF(SLinkNode *&L,ElemType a[],int n){
SLinkNode *s; int i;
//创建头结点
L=(SLinkNode *)malloc(sizeof(SLinkNode));
//头结点的next域置空
L->next=NULL;
//遍历a数组所有元素
for (i=0;i<n;i++){
s=(SLinkNode *)malloc(sizeof(SLinkNode));
//创建存放a[i]元素的新结点s
s->data=a[i];
//将s插在头结点之后
s->next=L->next;
//新的最前面结点是s了,更新之。
L->next=s;
}
}
//尾插法建表
void CreateListR(SLinkNode *&L,ElemType a[],int n){
SLinkNode *s,*tc; int i;
//创建头结点
L=(SLinkNode *)malloc(sizeof(SLinkNode));
//tc为L的尾结点指针
tc=L;
for (i=0;i<n;i++){
s=(SLinkNode *)malloc(sizeof(SLinkNode));
//创建存放a[i]元素的新结点s
s->data=a[i];
//将s结点插入tc结点之后
tc->next=s;
//更新尾结点!现在的尾巴是刚插入的s结点了
tc=s;
}
//尾结点next域置为NULL
tc->next=NULL;
}
//确定单链表L中第一个元素值最大的结点
SLinkNode *Maxnode(SLinkNode *L){
SLinkNode *p = L->next,*maxp = p;
while(p != NULL){
//当p指向更大的结点,刷新maxp
if(maxp->data < p->data){
maxp = p;
}
//p指向下一个结点
p = p->next;
}
return maxp;
}
//找到指定结点的前驱节点(这里指定以最大的结点为例)
SLinkNode *Premaxnode(SLinkNode *L){
SLinkNode *p = L->next, *pre = L,*maxp = p,*maxpre = pre;
while(p != NULL){
//找到更大结点,刷新maxp、maxpre
if(maxp->data < p->data){
maxp = p;
maxpre = pre;
}
//更新pre、p
pre = p;
p = p->next;
}
//不存在这样的结点(maxpre仍然指向头结点,即NULL)
if(maxpre == NULL){
return NULL;
}
else return maxpre;
}
//基于整体建表的设计
//逆置整个单链表
void Reverse(SLinkNode *&L){
//p是要插入的结点;q标记当前操作结点的下一个,用于记录头插的下一个结点;
//实现了倒置建表
SLinkNode *p = L->next, *q;
//将L置为空链表
L->next = NULL;
//遍历整个原链表
while (p != NULL){
//下一地址赋值更新
q = p->next;
//找到头插位置,头插
p->next = L->next;
//刷新新的头插位置
L->next = p;
//找到下一个链表结点。
p = q;
}
}
//将所有的负数节点移动到前面(如果存在这样的节点),中间是为0的节点(如果存在这样的节点),最后是为正数的节点(如果存在这样的节点)。
void Move(SLinkNode *&L){
//检索指针
SLinkNode *p = L->next;
//结果链表的赋值指针
SLinkNode *pp = L->next;
int i=0,j=0;
int a[MAX_SIZE];
int b[MAX_SIZE];
int zerocount = 0;
while(p!=NULL){
//找到负数,计入头插数组
if(p->data<0){
a[j] = p->data;
j++;
}
//找到0,计数0的个数
else if(p->data == 0){
zerocount ++;
}
//找到正数,计入尾插
else{
b[i] = p->data;
i++;
}
p = p->next;
}
//头插负数
for(int k=0; k<j; k++){
pp->data = a[k];
pp = pp->next;
}
//接着插0
for(int k=0; k<zerocount;k++){
pp->data = 0;
pp=pp->next;
}
//接着插正数
for(int k=0;k<i;k++){
pp->data = b[k];
pp=pp->next;
}
}
//真是个垃圾算法
//将所有的负数节点移动到前面(如果存在这样的节点),中间是为0的节点(如果存在这样的节点),最后是为正数的节点(如果存在这样的节点)。
//算法2:
void Move2(SLinkNode *&L){
SLinkNode *p = L->next,*pre = L;
SLinkNode *tc;
//初始化链表结点
L->next = NULL;
tc = L;
int zeroNum = 0;
while(p != NULL){
//小于0,头插
if(p->data < 0){
pre->data = p->data;
pre->next = L->next;
L->next = pre;
//当插入第一个结点时,用tc存尾结点
if(pre->next == NULL){
tc = pre;
}
}
//等于0,计数
else if(p->data == 0){
zeroNum++;
}//大于0,尾插
else{
pre->data = p->data;
tc->next = pre;
tc = pre;
tc->next = NULL;
}
p = p->next;
}
//找到最后一个为正的结点,在其后和负数之间插入零
p = L->next;
//用flag标记负数的位置
SLinkNode *flag;
while(p->data < 0){
p = p->next;
}
flag = p->next;
//这里插入0是新创建结点还是怎样??试一下吧
for(int i = 0;i<zeroNum;i++){
pre = (SLinkNode *)malloc(sizeof(SLinkNode));
pre->data = 0;
p->next = pre;
pre->next = NULL;
}
//最后一个pre的next指向flag。
pre->next = flag;
}
//链表实现所有奇数移到所有偶数前面
//思路:找到奇数,头插;找到偶数,尾插
void Move_1(SLinkNode *L){
SLinkNode *p = L->next,*q,*tc;
//将结果单链表L置为空表
L->next = NULL;
//tc为尾结点指针
tc = L;
//扫描链表所有结点
while (p != NULL){
//找到奇数节点
if(p->data%2 == 1){
//q临时保存p的后面结点
q = p->next;
//L为空表,插p入开头
if(L->next == NULL){
p->next = L->next;
L->next = p;
//尾结点为p
tc = p;
}
//L不为空:头插p
else{
p->next = L->next;
L->next = p;
}
p = q;
}
//找到偶数节点:尾插入
else{
//赋值尾结点:尾结点指针域指向p
tc->next = p;
//尾结点是p
tc = p;
//p指向下一个数据:对原链表下一个数据操作
p = p->next;
}
}
//重置尾结点为空
tc->next = NULL;
}
//二路归并
void Merge(SLinkNode *ha,SLinkNode *hb,SLinkNode *&hc){
SLinkNode *pa = ha->next, *pb = hb->next, *tc;
//将ha的头结点作为hc的头结点
hc = ha;
//tc总是指向结果单链表hc的尾结点
tc = hc;
//释放hb头结点
free(hb);
//当两个被并单链表都有待并元素时:
while(pa!=NULL && pb!=NULL){
//pa结点大,接到tc之后
if(pa->data < pb->data){
//尾插
tc->next = pa;
tc = pa;
pa = pa->next;
}
//pb结点大,接到tc之后
else if(pa->data > pb->data){
//尾插pb
tc->next = pb;
//更新尾巴结点为pb
tc = pb;
//更新b链表待排元素为当前进入hc的结点的后继
pb = pb->next;
}
}
//置零尾结点;
//这一行可否删去?——不可以。如果全部排完,则要标志链表已到头。标记的方法就是尾结点指针域置空,即走不下去了
tc->next = NULL;
//如果pa还有剩余结点,全部接入。 note-pa有限度,其尾巴结点的指针域指向NULL,即标志着链表的终止。
if(pa != NULL){
tc->next = pa;
}
//pb还有剩余,接入
if(pb != NULL){
tc->next = pb;
}
}
//空间复杂度O(1)--(没有新建hc的头结点和新的结点,而是利用ha和hb的所有结点重新链接产生hc的)
//但调用此算法后,ha和hb就被破坏,ha和hb不复存在
//对现有的内存进行操作,而不是对空的事先安排好的空间操作,其时间消耗是否要比后者大?
//时间复杂度O(m+n)
//递增排列的ha、hb设计算法将他们公共结点置入hc。
void Commelem(SLinkNode *ha,SLinkNode *hb,SLinkNode *&hc){
SLinkNode *pa = ha->next,*pb = hb->next,*tc,*s;
//创建hc的头结点
hc = (SLinkNode *)malloc(sizeof(SLinkNode));
//yc指向新建单链表的hc的尾结点
tc = hc;
while(ha != NULL && pb != NULL){
if(pa->data < pb->data){
pa = pa->next;
}
else if(pa->data > pb->data){
pb = pb->next;
}
//找到两个链表都有的元素
else{
//创建新结点
s = (SLinkNode *)malloc(sizeof(SLinkNode));
//数据域赋值
s->data = pa->data;
//尾插
tc->next = s;
//更新尾结点
tc = s;
//pa、pb同时后移一个结点
pa = pa->next;
pb = pb->next;
}
}
//标志结束hc单链表
tc->next = NULL;
}
//单链表的排序算法
//举例:学生单链表结点类型声明
typedef struct node_stu{
//数据域
char name[10];
int score;
//指针域
struct node_stu *next;
}StudList;
void CreateStudent(StudList *&sl){
int n,i;
StudList *s,*tc;
//创建头结点
sl = (StudList *)malloc(sizeof(StudList));
//初始化尾结点,同头结点
tc = sl;
printf(" 学生人数:");
scanf("%d",&n);
for(i = 0;i<n;i++){
s = (StudList *)malloc(sizeof(StudList));
printf(" 第%d个学生姓名和成绩:",i+1);
scanf("%s,%d",s->name,&s->score);
//尾插s
tc->next = s;
tc = s;
}
tc->next = NULL;
}
void DestroyStuList(StudList *&L){
StudList *pre = L,*p = pre->next;
//当链表中下一元素不为空(即下一个结点不是尾结点,即NULL),free当前,pre和p都移一位
while(p != NULL){
free(pre);
pre = p;p = p->next;
}
//最后把剩下的free掉
free(pre);
}
//打印信息;可做模版
void DispStuList(StudList *L){
StudList *p = L->next;
int i = 1;
printf(" 名次 姓 名 成绩\n");
//当没有扫描完整个链表
while(p != NULL){
printf(" %d\t\t",i++);
printf("%s\t\t%d\t\t",p->name,p->score);
//指向下一个结点
p = p->next;
}
}
//将单链表按成绩递减排序【链表排序】
void SortStuList(StudList *&L){
//pre-上一个;p-当前;q-下一个
StudList *p,*pre,*q;
p = L->next->next;
//构造一个致函有一个数据结点的有序结果表
L->next->next = NULL;
//当【原表】没有扫描完
while(p != NULL){
//q保存p结点的后继的指针
q = p->next;
//从有序表头进行比较,pre指向插入p结点的前驱,【等待插入】
pre = L;
//找到插入p结点的前驱pre
//当已建好的链表没有扫描结束,且当扫描到的结点大于带插入的结点时:扫描指针后移
while(pre->next != NULL && pre->next->score > p->score){
pre = pre->next;
}//链表中下一个结点小于待插入节点时:插入该结点
p->next = pre->next;
pre->next = p;
//将之前保存的p后面结点的地址给p,相当于扫描原链表的下一结点。
p = q;
}
}
//循环单链表内容:
//初始化单链表L
void InitList_Cyc(SLinkNode *&L){
//创建头结点L
L=(SLinkNode *)malloc(sizeof(SLinkNode));
L->next=L;
}
//销毁单链表L
void DestroyList_Cyc(SLinkNode *&L){
SLinkNode *pre=L,*p=pre->next;
while (p!=L){
free(pre);
pre=p; p=p->next; //pre、p同步后移
}
free(pre);
}
//求长度
void GetLength_Cyc(SLinkNode *L){
int i=0;
SLinkNode *p=L->next;
while(p != L){
i++;
p=p->next;
}
printf("%d\n",i);
}
//求第i个结点值
int GetElem_Cyc(SLinkNode *L,int i){
int j=1;
//p指向头结点,计数器j置为0
SLinkNode *p=L->next;
if (i<=0) return 0; //参数i错误返回0
while (p!=L && j<i){
j++;
p=p->next;
}
//未找到返回0
if (p==L)
return 0;
//找到后返回1
else{
printf("%d\n",p->data);
return 1;
}
}
//求第一个值为e的结点位置
int Locate(SLinkNode *L){
SLinkNode *p=L->next;
int j=1; //p指向第一个数据结点,j置为其序号1
while (p!=L && p->data!=97){
p=p->next;
j++;
}
if (p==L) return(0); //未找到返回0
else return(j); //找到后返回其序号
}
//插入结点值为x的结点
int InsElem_Cyc(SLinkNode *&L,ElemType x,int i){
int j=1;
SLinkNode *p=L->next,*s;
//参数i错误返回0
if (i<=0) return 0;
//查找第i-1个结点p
while (p!=L && j<i-1){
j++;
p=p->next;
}
//未找到第i-1个结点时返回0
if (p==L) return 0;
//找到第i-1个结点p
else{
s=(SLinkNode *)malloc(sizeof(SLinkNode));
s->data=x; //创建存放元素x的新结点s
s->next=p->next; //将s结点插入到p结点之后
p->next=s;
return 1; //插入运算成功,返回1
}
}
//删除结点
int DelElem_Cyc(SLinkNode *&L,int i){
int j=1;
SLinkNode *p=L->next,*q;
if (i<=0) return 0; //参数i错误返回0
//查找第i-1个结点
while (p!=L && j<i-1){
j++;
p=p->next;
}
//未找到第i-1个结点时返回0
if (p==L) return 0;
//找到第i-1个结点p
else{
//q指向被删结点
q=p->next;
//没有第i个结点时返回0
if (q==L)
return 0;
else{
//从单链表中删除q结点
p->next=q->next;
free(q);
return 1;
}
}
}
//输出单链表
void DispList_Cyc(SLinkNode *L){
SLinkNode *p=L->next;
while (p!=L){
cout<<p->data<<" ";
p=p->next;
}
printf("\n");
}
//头插法建表
void CreateListF_Cyc(SLinkNode *&L,ElemType a[],int n){
SLinkNode *s; int i;
L=(SLinkNode *)malloc(sizeof(SLinkNode)); //创建头结点
L->next=L; //头结点的next域置空
//遍历a数组所有元素
for (i=0;i<n;i++){
s=(SLinkNode *)malloc(sizeof(SLinkNode));
s->data=a[i]; //创建存放a[i]元素的新结点s
s->next=L->next; //将s插在头结点之后
L->next=s;
}
}
//尾插法建表
void CreateListR_Cyc(SLinkNode *&L,ElemType a[],int n){
SLinkNode *s,*tc; int i;
L=(SLinkNode *)malloc(sizeof(SLinkNode)); //创建头结点
tc=L; //tc为L的尾结点指针
for (i=0;i<n;i++){
s=(SLinkNode *)malloc(sizeof(SLinkNode));
s->data=a[i]; //创建存放a[i]元素的新结点s
tc->next=s; //将s结点插入tc结点之后
tc=s;
}
tc->next=L; //尾结点next域置为NULL
}
//循环单链表算法设计示例
//递增有序链表,删除所有x
int DelAllx(SLinkNode *&L,ElemType x){
SLinkNode *pre = L,*p = L->next;
while(p != L && p->data != x){
pre = p;
p = p->next;
}
if(p == L) return 0;
while(p != L && p->data == x){
pre->next = p->next;
free(p);
p = pre->next;
}
return 1;
}
//非递增链表 删除所有x 自己写的 没有验证正确性
int DelAllx_2(SLinkNode *&L,ElemType x){
SLinkNode *pre = L,*p = L->next;
//如果整个表没有x,返回0
while(p != L && p->data != x){
pre = p;
p = p->next;
}
if(p == L) return 0;
//遇到x,继续遍历整个表删除所有x
while(p != L){
while(p != L && p->data == x){
pre->next = p->next;
free(p);
p = p->next;
}
p = p->next;
}
//有x并且被删除,返回1
return 1;
}
//循环单链表求解Joseph问题
//小孩类,以便构造小孩循环圈(循环单链表)
typedef struct node_3{
int no;
struct node_3 *next;
}Child;
void CreateList_Child(Child *&L, int n){
int i;
Child *p,*tc;
L = (Child *)malloc(sizeof(Child));
L->no = 1;
//循环单链表:尾结点始终指向L
tc = L;
for(i = 2;i<=n;i++){
p = (Child*)malloc(sizeof(Child));
p->no = i;
tc->next = p;
tc = p;
}
}
//约瑟夫问题 解决函数
void Joseph(int n,int m){
int i,j;
Child *L,*p,*q;
CreateList_Child(L, n);
for(i = 1;i<=n;i++){
p = L;
j = 1;
while(j<m-1){
j++;
p = p->next;
}
q = p->next;
printf("%d ",q->no);
p->next = q->next;
free(q);
L = p->next;
}
}
//约瑟夫问题 主函数
void Joseph_main(){
int n,m;
printf("请依次输入人数、出列的报数:");
cin>>n>>m;
printf("n=%d,m=%d的约瑟夫序列:",n,m);
Joseph(n, m);
printf("\n");
}
//--------------------双链表------------------------
//双链表结点定义
typedef struct node_DoubleLinked {
//数据域
ElemType data;
//指针域:分别指向后继、前驱结点
struct node_DoubleLinked *prior,*next;
}DLinkNode;
void InitList_D(DLinkNode *&L){
L = (DLinkNode *)malloc(sizeof(DLinkNode));
L->prior = L->next = NULL;
}
bool IsBlank_CD(DLinkNode *L){
if(L->next == L) return 1;
else return 0;
}
void DestroyList_D(DLinkNode *&L){
DLinkNode *pre = L,*p = pre->next;
while(p != NULL){
free(pre);
pre = p;
p = p->next;
}
}
int GetLength_D(DLinkNode *L){
int i = 0;
DLinkNode *p = L->next;
while(p != NULL){
i++;
p = p->next;
}
return i;
}
//求链表第i个元素
int GetElem_D(DLinkNode *L,int i,ElemType &e){
int j = 0;
DLinkNode *p = L;
if(i <= 0) return 0;
while(p != NULL && j<i){
j++;
p = p->next;
}
if(p == NULL) return 0;
else{
e = p->data;
return 1;
}
}
//在链表中,第一个指定元素e的位置
int Locate_D(DLinkNode *L,ElemType e){
DLinkNode *p = L->next;
int i = 1;
while(p != NULL && p->data != e){
p = p->next;
i++;
}
if(p == NULL) return 0;
else return i;
}
//将数据x插入双链表第i个结点
int InsElem_D(DLinkNode *&L,ElemType x,int i){
int j = 0;
//s是待插入的结点
DLinkNode *p = L,*s;
if(i <= 0) return 0;
//找到第i-1个结点p
while(p != NULL && j<i-1){
j++;
p = p->next;
}
//待插入位置的前一个结点就已经是空,无法插入,返回-1
if(p == NULL) return 0;
else{
//建立结点
s = (DLinkNode *)malloc(sizeof(DLinkNode));
s->data = x;
//插入:s的下一个结点是链表中p的下一个
s->next = p->next;
//如果p不是最后一个结点,需要调整p的prior指向待插入结点s
if(p->next != NULL){
p->next->prior = s;
}
//调整s的prior为p
s->prior = p;
//调整p的next为s
p->next = s;
return 1;
}
}
//将双链表第i个结点删除
int DelElem_D(DLinkNode *&L,int i){
int j = 0;
DLinkNode *p = L,*pre;
if(i <= 0) return 0;
//找到第i个结点
while(p != NULL && j<i){
j++;
p = p->next;
}
//如果第i个结点已经为空,无法删除,返回0
if(p == NULL) return 0;
//删除第i个结点
else{
//找到第i个结点的前面结点
pre = p->prior;
//如果第i个结点后面仍有结点,需要调整该结点的prior指向pre
if(p->next != NULL){
p->next->prior = pre;
}
//pre的下一个指向p的下一个
pre->next = p->next;
//释放p结点,删除成功,返回1
free(p);
return 1;
}
}
//输出双链币啊:与单链表完全相同
void DispList_D(DLinkNode *L){
DLinkNode *p = L->next;
while(p != NULL){
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
//创建整体双链表的算法:
void CreateListF_D(DLinkNode *&L,ElemType a[],int n){
DLinkNode *s;
int i;
//创建头结点
L = (DLinkNode *)malloc(sizeof(DLinkNode));
L->next = NULL;
for(i = 0;i<n;i++){
//创建新结点S,赋数据域值
s = (DLinkNode *)malloc(sizeof(DLinkNode));
s->data = a[i];
//头插结点
s->next = L->next ;
s->prior = L;
//当L中已有结点时,需要操作最前面结点的prior
if(L->next != NULL){
L->next->prior = s;
}
//更新头结点的next域
L->next = s;
}
}
void CreateListR_D(DLinkNode *&L,ElemType a[],int n){
DLinkNode *s,*tc;
int i;
L = (DLinkNode *)malloc(sizeof(DLinkNode));
tc = L;
for(i = 0;i<n;i++){
s = (DLinkNode *)malloc(sizeof(DLinkNode));
s->data = a[i];
tc->next = s;
s->prior = tc;
tc = s;
}
tc->next = NULL;
}
//双链表的算法设计示例
//交换值为x的节点和其后继节点
int swap_D(DLinkNode *L,ElemType x){
DLinkNode *p = L->next,*post;
//找到第一个值为x的结点
while(p != NULL && p->data != x){
p = p->next;
}
//没找到,返回0
if(p == NULL) return 0;
//找到了,开始交换。需要更新六个指针:0-1-2-3改为0-2-1-3
else{
//post指向p的后继结点
post = p->next;
//post即后继结点!=0,可以交换:
if(post != NULL){
//更改p前面结点的next域
p->prior->next = post;
post->prior = p->prior;
p->next = post->next;
//post后面还有结点的话,需要更新这个结点的prior
if(post->next != NULL){
post->next->prior = p;
}
post->next = p;
p->prior = post;
return 1;
}
else return 0;
}
}
//------------循环双链表 CD-Cycle Double Linke--------------
//初始化双链表
void InitList_CD(DLinkNode *&L) {
L = (DLinkNode *)malloc(sizeof(DLinkNode));
L->next =L->prior = NULL;
}
//释放单链表
void DestroyList_CD(DLinkNode *&L) {
DLinkNode *pre = L, *p = pre->next;
while (p != NULL) {
free(pre);
pre = p;
p = p->next;
}
free(pre);
}
//获取链表长度
int GetLength_CD(DLinkNode *L) {
DLinkNode *p = L->next;
int num = 0;
while (p != L) {
num++;
p = p->next;
}
return num;
}
//获取元素的值
ElemType GetElem1_CD(DLinkNode *L, int n) {
if (n > GetLength_CD(L)||n<=0) {
cout << "超出长度,错误\n";
return 0;
}
else {
DLinkNode *p = L->next, *pre = L;
for (int i = 1; i < n; i++) {
pre = p;
p = p->next;
}
return p->data;
}
}
//求线性表中第i个元素运算算法
int GetElem_CD(DLinkNode *L,int i,ElemType &e){
int j = 1;
DLinkNode *p = L->next;
if(i <= 0) return 0;
//找到第i个元素
while(p != L && j<i){
j++;
p = p->next;
}
//没找到,由于是循环双链表,循环一圈后回到头结点L
if(p == L) return 0;
//引用返回元素值
else{
e = p->data;
return 1;
}
}
//获取元素在链表中的位置 (按值查找)
int Locate_CD(DLinkNode *L, ElemType x) {
int i = 1;
DLinkNode *p = L->next;
while (p != L && p->data != x) {
p = p->next;
i++;
}
if(p == L) return 0;
else return i;
return 0;
}
//插入元素
int InsElem_CD(DLinkNode *&L,ElemType x,int i) {
int j = 1;
DLinkNode *p = L->next, *pre = L,*s;
while(p != L && j < i){
j++;
p = p->next;
}
//当p = L且i>j+1(这是j存的是L中的结点数)(上面的while当p==L时停止)
//说明i>链表中的元素数。参数错误,返回0
//这里第二个判断条件i>j+1是否可以删去?
if(p == L && i>j+1) return 0;
//找到第i个结点,称p。
else{
//创建s结点,赋值数据域
s = (DLinkNode *)malloc(sizeof(DLinkNode));
s->data = x;
//插入s结点:
//pre存第i个结点p的前面节点。
//更新前面结点的next和s的prior
pre = p->prior;
s->prior = pre;
pre->next = s;
//更新s后面结点,即p的prior即s的next
p->prior = s;
s->next = p;
return 1;
}
}
//删除第i个结点运算算法
int DelElem_CD(DLinkNode *&L, int i) {
int j = 0;
DLinkNode *p = L, *pre;
if (i <= 0) return 0;
while (p != NULL && j < i) {
j++;
p = p->next;
}
if (p == NULL) return 0;
//找到第i个结点p
else {
//p的前面结点为pre
pre = p->prior;
//如果p后面还有结点,赋值其prior结点
if (p->next != NULL)
p->next->prior = pre;
//pre指向p的next(如果后面没有结点,即为NULL)
pre->next = p->next;
//释放p空间
free(p);
return 1;
}
}
//输出线性表
void DispList_CD(DLinkNode *L){
DLinkNode *p = L->next;
while(p != L){
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
//循环双链表的算法设计示例
//将带头结点的循环双链表L的所有结点逆置
void Reserve_CD(DLinkNode *&L){
DLinkNode *p = L->next,*q;
//构造一个空的循环双链表
L->next = L->prior = L;
while(p != L){
q = p->next;
//将p插入表头(头插法)
p->next = L->next;
L->next->prior = p;
L->next = p;
p->prior = L;
p = q;
}
}
//创建整体循环双链表的算法:
void CreateListF_CD(DLinkNode *&L,ElemType a[],int n){
DLinkNode *s,*tc;
int i;
//创建头结点
L = (DLinkNode *)malloc(sizeof(DLinkNode));
//将双链表中结尾点的next指向头结点;将头结点的prior指向尾结点。
L->next = L->prior = L;
//创建第一结点s,赋数据域值;
//建链表完成后,该结点相当于尾结点,需要单独保存。
s = (DLinkNode *)malloc(sizeof(DLinkNode));
s->data = a[0];
//头插结点
s->next = L->next ;
s->prior = L;
//tc保存尾结点。
tc = s;
//继续创建剩下结点:
for(i = 1;i<n;i++){
//创建新结点S,赋数据域值
s = (DLinkNode *)malloc(sizeof(DLinkNode));
s->data = a[i];
//头插结点
s->next = L->next ;
s->prior = L;
//当L中已有结点时,需要操作最前面结点的prior
if(L->next != NULL){
L->next->prior = s;
}
//更新头结点的next域
L->next = s;
}
//上述算法可以写在一个for循环,只需加一个判断条件;但可读性较差。
//完成循环链表的闭环:
//尾结点的next指向头结点L;
tc->next = L;
//头结点的prior指向尾结点。
L->prior = tc;
}
void CreateListR_CD(DLinkNode *&L,ElemType a[],int n){
DLinkNode *s,*tc;
int i;
L = (DLinkNode *)malloc(sizeof(DLinkNode));
//将双链表中结尾点的next指向头结点;将头结点的prior指向尾结点。
L->next = L->prior = L;
tc = L;
for(i = 0;i<n;i++){
//创建新结点s,赋值数据域
s = (DLinkNode *)malloc(sizeof(DLinkNode));
s->data = a[i];
//原来尾结点的next指向新结点s;
tc->next = s;
//新结点的prior只指向原来的尾结点
s->prior = tc;
//更新尾结点。
tc = s;
}
//循环:将尾结点的next指向L;
tc->next = L;
//头结点的prior指向尾结点。
L->prior = tc;
}
//判断序列中元素是否对称:对称则从前往后读和从后往前读所得序列完全一样
int Symmetric(DLinkNode *L){
int flag = 1;
DLinkNode *p = L->next,*q = L->prior;
while(flag == 1){
if(p->data != q->data){
flag = 0;
}
else{
if(p == q || p->next == q){
break;
}
p = p->next;
q = q->prior;
}
}
return flag;
}
//---------------------DNA排序—--------------------
//DNA结点类定义
typedef char ElemType_DNA;
typedef struct{
//DNA链-字符数组
ElemType_DNA data[MAX_SIZE];
//逆序数
int flag;
//DNA链的长度
int length;
} DNA;
//计算逆序数
int countInverseNumber(char a[],int n){
//c是逆序数;初始化逆序数为0
int InverseNum = 0;
//遍历整个DNA链
for(int i=0;i<n-1;i++){
//遍历当前字符的后面字符
for(int j=i+1;j<n;j++){
//如果后面有字符比当前的大,逆序数+1
if(a[i]>a[j])
InverseNum++;
}
}
return InverseNum;
}
//交互式生成DNA L[]
void CreateDNA(DNA L[MAX_SIZE],int &n,int &m){
//m是DNA链的长度,n是DNA链数;
cin>>m>>n;
//创建DNA链表数组,m个
//每个DNA链表的长度都为n
L[m].length=n;
//循环输入L[].data[],共n链
for(int i = 0;i < n;i++){
//赋值每一个DNA链的长度为m
L[i].length = m;
for(int j = 0;j < m;j++){
cin>>L[i].data[j];
}
}
//计算他们的逆序数,存到DNA.flag
for(int i = 0;i < n;i++){
L[i].flag = countInverseNumber(L[i].data, n);
}
}
//给n链dna按照逆序数从小到大排序
void bubbleSort_DNA(DNA L[],int n){
//结构体排序 bubbleSort,升序排序
DNA temp;
for(int i = 1;i<n;i++){
for(int j = 0;j<n-1;j++){
//如果出现前一个大于后一个,交换他们的位置
if(L[j].flag > L[j+1].flag){
temp = L[j];
L[j] = L[j+1];
L[j+1] = temp;
}
}
}
}
//输出n条长度为m的DNA链
void DispDNA(DNA L[],int m,int n){
for(int i = 0;i<n;i++){
for(int j = 0;j<m;j++){
printf("%c",L[i].data[j]);
}
printf("\n");
}
}
void DNA_main(){
DNA L[MAX_SIZE];
int m,n;
CreateDNA(L,m,n);
bubbleSort_DNA(L,n);
DispDNA(L,m,n);
}
//两递增排序的线性表A、B,含有m、n个整数元素,假设他们各不相同,求m+n个元素中第k小的元素
int Topk_1(SqList A, SqList B, int k, ElemType &e){
int i = 0,j = 0;
if(k<1||k>A.length + B.length){
return 0;
}
while(i<A.length && j<B.length){
//每次归并一个元素,k减1
k--;
//归并的较小的元素为A.[i]
if(A.data[i] < B.data[j]){
//k为0时,当前归并的元素就是原第k小的元素
if(k == 0){
e = A.data[i];
return 1;
}
i++;
}
//归并的较小的元素为B.[j]
else{
if(k == 0){
e = B.data[j];
return 1;
}
j++;
}
}
//A没有扫描完毕
if(i<A.length){
e = A.data[i+k-1];
}
//B没有扫描完毕
else if(j<B.length){
e = B.data[j+k-1];
}
return 1;
}
//简化判断:有一个数组扫描完后,置其剩余元素为INF
int Topk_2(SqList A, SqList B, int k, ElemType &e){
int i = 0,j = 0;
//参数错误,返回0
if(k<1||k>A.length + B.length){
return 0;
}
while(1){
//每次归并一个元素,k减1
k--;
int x = (i<A.length?A.data[i]:INF);
int y = (j<B.length?B.data[j]:INF);
if(x<y){
if(k == 0){
e = x;
return 1;
}
i++;
}
else{
if(k == 0){
e = y;
return 1;
}
j++;
}
}
}
//删除自第i个元素开始的k个元素
int Deletek(SqList &L, int i,int k){
int j;
//i和k参数不合法,返回0
if(i<1 ||k<1 || i+k-1>L.length){
return 0;
}
//将下标i+k-1之后元素前移至i处
for(j = i+k-1;j<L.length;j++){
L.data[j-k] = L.data[j];
}
//L的长度-k
L.length-=k;
return 1;
}
int main(){
SLinkNode *L;
int n;
ElemType a[MAX_SIZE];
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
CreateListR(L,a,n); //尾插法建表
Move2(L);
DispList(L);
DestroyList(L);
return 0;
}
本文详细介绍了C++实现的数据结构,包括单链表、顺序表的操作,如初始化、销毁、查找、插入、删除等,并展示了如何使用C++实现链表排序、逆置、元素移动等算法。此外,还涉及到了循环链表和双链表的相关操作,如创建、销毁、查找、插入、删除等。最后,讨论了如何在实际场景中应用这些数据结构和算法,如Joseph问题和DNA排序。

2393

被折叠的 条评论
为什么被折叠?



