主要是上学期链表的操作复习和进阶,书本是C语言版本的,然而书上代码是C++的,这属实很离谱。这次作业主要还是用了C语言的方式编写,以后直接写c++版本了(不过尽可能不用STL)。同时会在目录博客里发布C和C++的常见转化,方便各位理解书上的程序。平常建议直接创建cpp文件以防一些东西是c++的语法没法在c的文件中成功编译
[数据结构]NEFU 大二上 锐格实验参考 目录
题目 | 知识点 |
---|---|
8559 | 数组翻转 |
8553 | 单链表创建遍历 |
8554 | 单链表翻转 |
8555 | 插入维护有序单链表 |
8556 | 单链表删除节点 |
8557 | 有序单链表合并/单链表排序 |
8558 | 单链表拆分 |
8560 | 单链表实现多项式加法(本质是有序单链表创建和合并) |
很多题目是直接用了上题的代码所以不是所有函数都会被用到的,自己如果觉得代码太多了建议仔细看看调用了哪些函数。
原地翻转数组存储的线性表,下面提供了一种交换的方法,当然你也可以直接逆序输出
#include
#include
#include
#include
int arr[15];
int n;
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++)scanf("%d",&arr[i]);
for(int i=0;i<n;i++)printf("%d ",arr[i]);puts("");
for(int i=0;i<n/2;i++){
int tmp;
tmp=arr[i];
arr[i]=arr[n-i-1];
arr[n-i-1]=tmp;
}
for(int i=0;i<n;i++)printf("%d ",arr[i]);puts("");
return 0;
}
创建和遍历有头节点的单链表,采用了尾插法
#include
#include
#include
#include
#include
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;//LNode 主要用于一般节点,*LinkList主要用于头节点
void CreatList_Tail(LinkList &L){
L=(LNode *)malloc(sizeof (LNode));//等效于书上的new,不然要写c++
L->next=NULL;
LNode *r=L;//尾指针指向头节点
LNode *p;
int input;
while(~scanf("%d",&input)){
if(input==0)break;
p=(LNode *)malloc(sizeof (LNode));
p->data=input;
p->next=NULL;
r->next=p;
r=p;
}
}
void PrintList(LinkList &L){//打印链表
LNode *p;
p=L->next;
while(p!=NULL){
printf("%d ",p->data);
p=p->next;
}
}
int main(){
LinkList H;
CreatList_Tail(H);
PrintList(H);
return 0;
}
翻转单链表,只需要把指针指向翻转即可
#include
#include
#include
#include
#include
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;//LNode 主要用于一般节点,*LinkList主要用于头节点
void CreatList_Tail(LinkList &L){//后插法创建链表
L=(LNode *)malloc(sizeof (LNode));//等效于书上的new,不然要写c++
L->next=NULL;
LNode *r=L;//尾指针指向头节点
LNode *p;
int input;
while(~scanf("%d",&input)){
if(input==0)break;
p=(LNode *)malloc(sizeof (LNode));
p->data=input;
p->next=NULL;
r->next=p;
r=p;
}
}
void PrintList(LinkList &L){//打印链表
LNode *p;
p=L->next;
while(p!=NULL){
printf("%d ",p->data);
p=p->next;
}
}
void ReverseList(LinkList &L) {//反转链表
if (L == NULL||L->next == NULL)return;
LNode* pre = NULL; //前驱结点
LNode* cur = L->next; //当前结点
LNode* nex; //后继结点
while (cur!=NULL) {
nex=cur->next;
cur->next=pre;
pre=cur;
cur=nex;
}
L->next=pre;
}
int main(){
LinkList H;
CreatList_Tail(H);
ReverseList(H);
PrintList(H);
return 0;
}
插入维护有序链表
#include
#include
#include
#include
#include
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;//LNode 主要用于一般节点,*LinkList主要用于头节点
void CreatList_Tail(LinkList &L){//后插法创建链表
L=(LNode *)malloc(sizeof (LNode));//等效于书上的new,不然要写c++
L->next=NULL;
LNode *r=L;//尾指针指向头节点
LNode *p;
int input;
while(~scanf("%d",&input)){
if(input==0)break;
p=(LNode *)malloc(sizeof (LNode));
p->data=input;
p->next=NULL;
r->next=p;
r=p;
}
}
void PrintList(LinkList &L){//打印链表
LNode *p;
p=L->next;
while(p!=NULL){
printf("%d ",p->data);
p=p->next;
}
}
void ReverseList(LinkList &L) {//反转链表
if (L == NULL||L->next == NULL)return;
LNode* pre = NULL; //前驱结点
LNode* cur = L->next; //当前结点
LNode* nex; //后继结点
while (cur!=NULL) {
nex=cur->next;
cur->next=pre;
pre=cur;
cur=nex;
}
L->next=pre;
}
void InsertList(LinkList &L,int x){//插入维护有序链表
LNode * p, * pre,* ins;
ins=(LNode *)malloc(sizeof (LNode));
pre=L;
p=L->next;
while(p!=NULL&&p->data<x){
pre=p;
p=p->next;
}
ins->data=x;
ins->next=p;
pre->next=ins;
}
int main(){
LinkList H;
H=(LNode *)malloc(sizeof (LNode));//等效于书上的new,不然要写c++
H->next=NULL;
int x;
while(~scanf("%d",&x)){
if(x==0)break;
InsertList(H,x);
}
PrintList(H);
return 0;
}
删除链表当中偶数点,当然你可以在创建链表的时候直接过滤掉偶数节点
#include
#include
#include
#include
#include
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;//LNode 主要用于一般节点,*LinkList主要用于头节点
void CreatList_Tail(LinkList &L){//后插法创建链表
L=(LNode *)malloc(sizeof (LNode));//等效于书上的new,不然要写c++
L->next=NULL;
LNode *r=L;//尾指针指向头节点
LNode *p;
int input;
while(~scanf("%d",&input)){
if(input==0)break;
p=(LNode *)malloc(sizeof (LNode));
p->data=input;
p->next=NULL;
r->next=p;
r=p;
}
}
void PrintList(LinkList &L){//打印链表
LNode *p;
p=L->next;
while(p!=NULL){
printf("%d ",p->data);
p=p->next;
}
}
void ReverseList(LinkList &L) {//反转链表
if (L == NULL||L->next == NULL)return;
LNode* pre = NULL; //前驱结点
LNode* cur = L->next; //当前结点
LNode* nex; //后继结点
while (cur!=NULL) {
nex=cur->next;
cur->next=pre;
pre=cur;
cur=nex;
}
L->next=pre;
}
void InsertList(LinkList &L,int x){//插入维护有序链表
LNode * p, * pre,* ins;
ins=(LNode *)malloc(sizeof (LNode));
pre=L;
p=L->next;
while(p!=NULL&&p->data<x){
pre=p;
p=p->next;
}
ins->data=x;
ins->next=p;
pre->next=ins;
}
void DeleteList(LinkList &L) {//删除符合某个条件的节点
LNode * p,* pre,*tmp;
pre=L;p=L->next;
while(p!=NULL){
if(p->data%2==0){//if里写删除规则
tmp=p;//直接用p释放后影响后续循环
pre->next=p->next;
p=p->next;//pre不用更新,p更新为下一个节点
free(tmp);//释放
}
else{
pre=p;
p=p->next;
}
}
}
int main(){
LinkList H;
CreatList_Tail(H);
DeleteList(H);
PrintList(H);
return 0;
}
创建两个有序链表,然后合并成一个有序链表。我是先合并然后直接写了链表排序的,如果想要先创建两个有序链表然后在合并可以参看最后那道多项式的代码。
#include
#include
#include
#include
#include
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;//LNode 主要用于一般节点,*LinkList主要用于头节点
void CreatList_Tail(LinkList &L){//后插法创建链表
L=(LNode *)malloc(sizeof (LNode));//等效于书上的new,不然要写c++
L->next=NULL;
LNode *r=L;//尾指针指向头节点
LNode *p;
int input;
while(~scanf("%d",&input)){
if(input==0)break;
p=(LNode *)malloc(sizeof (LNode));
p->data=input;
p->next=NULL;
r->next=p;
r=p;
}
}
void PrintList(LinkList &L){//打印链表
LNode *p;
p=L->next;
while(p!=NULL){
printf("%d ",p->data);
p=p->next;
}
}
void ReverseList(LinkList &L) {//反转链表
if (L == NULL||L->next == NULL)return;
LNode* pre = NULL; //前驱结点
LNode* cur = L->next; //当前结点
LNode* nex; //后继结点
while (cur!=NULL) {
nex=cur->next;
cur->next=pre;
pre=cur;
cur=nex;
}
L->next=pre;
}
void InsertList(LinkList &L,int x){//插入维护有序链表
LNode * p, * pre,* ins;
ins=(LNode *)malloc(sizeof (LNode));
pre=L;
p=L->next;
while(p!=NULL&&p->data<x){
pre=p;
p=p->next;
}
ins->data=x;
ins->next=p;
pre->next=ins;
}
void DeleteList(LinkList &L) {//删除符合某个条件的节点
LNode * p,* pre,*tmp;
pre=L;p=L->next;
while(p!=NULL){
if(p->data%2==0){//if里写删除规则
tmp=p;//直接用p释放后影响后续循环
pre->next=p->next;
p=p->next;//pre不用更新,p更新为下一个节点
free(tmp);//释放
}
else{
pre=p;
p=p->next;
}
}
}
void MergeList(LinkList &LA,LinkList &LB,LinkList &LC){//合并
LNode *pa=LA->next,*pb=LB->next;
LC=LA;
LNode *pc=LC;
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);
}
void SortList(LinkList &L){//排序
LNode *p,*q;
for(p=L->next;p!=NULL;p=p->next){
for(q=p->next;q!=NULL;q=q->next){
if(p->data<q->data) {
int x;
x=q->data;
q->data=p->data;
p->data=x;
}
}
}
}
int main(){
LinkList H_1,H_2,H_3;
CreatList_Tail(H_1);
CreatList_Tail(H_2);
MergeList(H_1,H_2,H_3);
SortList(H_3);
PrintList(H_3);
return 0;
}
将链表分解成两个链表分别存储奇数和偶数的。
题目说尽量利用已知空间,不清楚自己写得是不是符合要求
创建了三个空链表,一个读入后按要求拆分到第二个和第三个链表,然后释放第一个链表。
那么最多的时候我们在空间上用了2倍的第一个链表的大小(链表1+链表2+链表3)
如果要减少的话可以考虑
创建链表1->遍历链表1如果是奇数就打印->遍历链表2如果是偶数就打印->释放链表1。这样最多空间用一个链表1的大小
就练习代码能力而言可以选择第一种,不过第二种代码又简单空间又小
#include
#include
#include
#include
#include
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;//LNode 主要用于一般节点,*LinkList主要用于头节点
void CreatList_Tail(LinkList &L){//后插法创建链表
L=(LNode *)malloc(sizeof (LNode));//等效于书上的new,不然要写c++
L->next=NULL;
LNode *r=L;//尾指针指向头节点
LNode *p;
int input;
while(~scanf("%d",&input)){
if(input==0)break;
p=(LNode *)malloc(sizeof (LNode));
p->data=input;
p->next=NULL;
r->next=p;
r=p;
}
}
void PrintList(LinkList &L){//打印链表
LNode *p;
p=L->next;
while(p!=NULL){
printf("%d ",p->data);
p=p->next;
}
puts("");
}
void ReverseList(LinkList &L) {//反转链表
if (L == NULL||L->next == NULL)return;
LNode* pre = NULL; //前驱结点
LNode* cur = L->next; //当前结点
LNode* nex; //后继结点
while (cur!=NULL) {
nex=cur->next;
cur->next=pre;
pre=cur;
cur=nex;
}
L->next=pre;
}
void InsertList(LinkList &L,int x){//插入链表
LNode * p, * pre,* ins;
ins=(LNode *)malloc(sizeof (LNode));
pre=L;
p=L->next;
while(p!=NULL){
pre=p;
p=p->next;
}
ins->data=x;
ins->next=p;
pre->next=ins;
}
void DeleteList(LinkList &L) {//删除符合某个条件的节点
LNode * p,* pre,*tmp;
pre=L;p=L->next;
while(p!=NULL){
if(p->data%2==0){//if里写删除规则
tmp=p;//直接用p释放后影响后续循环
pre->next=p->next;
p=p->next;//pre不用更新,p更新为下一个节点
free(tmp);//释放
}
else{
pre=p;
p=p->next;
}
}
}
void MergeList(LinkList &LA,LinkList &LB,LinkList &LC){//合并
LNode *pa=LA->next,*pb=LB->next;
LC=LA;
LNode *pc=LC;
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);
}
void SortList(LinkList &L){//排序
LNode *p,*q;
for(p=L->next;p!=NULL;p=p->next){
for(q=p->next;q!=NULL;q=q->next){
if(p->data<q->data) {
int x;
x=q->data;
q->data=p->data;
p->data=x;
}
}
}
}
void SplitList(LinkList &LA,LinkList &LB,LinkList &LC){//拆分链表
LNode * p,* pre,*tmp;
pre=LA;p=LA->next;
LB=(LNode *)malloc(sizeof (LNode));
LC=(LNode *)malloc(sizeof (LNode));
while(p!=NULL){
if(abs(p->data)%2==0)InsertList(LC,p->data);
else InsertList(LB,p->data);
pre=p;
p=p->next;
}
free(LA);
}
int main(){
LinkList H_1,H_2,H_3;
CreatList_Tail(H_1);
SplitList(H_1,H_2,H_3);
PrintList(H_2);
PrintList(H_3);
return 0;
}
单链表创建多项式,多项式加法。
本质上就是考有序单链表创建插入和合并两个有序单链表嘛!注释可以直接看书上的
#include
#include
#include
#include
#include
typedef struct PNode{
int coef;//系数
int expn;//指数
struct PNode *next;
}PNode,*Polynomial;
void InsertPolyn(Polynomial &P,PNode *s){
PNode *pre,*p;
pre=P;
p=P->next;
while(p!=NULL&&p->expn<s->expn){
pre=p;
p=p->next;
}
s->next=p;
pre->next=s;
}
void CreatePolyn(Polynomial &P,int n){
PNode *s,*pre,*p;
P=(PNode *)malloc(sizeof (PNode));P->next=NULL;
for(int i=1;i<=n;i++){
PNode *s;
s=(PNode *)malloc(sizeof (PNode));
scanf("%d,%d",&s->coef,&s->expn);
InsertPolyn(P,s);
}
}
void AddPolyn(Polynomial &PA,Polynomial &PB){
PNode *p1=PA->next,*p2=PB->next;
PNode *p3=PA,*tmp;
while(p1&&p2){
if(p1->expn==p2->expn){
if(p1->coef+p2->coef!=0){
p1->coef+=p2->coef;
p3->next=p1;p3=p1;
p1=p1->next;
tmp=p2;p2=p2->next;free(tmp);
}
else{
tmp=p1;p1=p1->next;free(tmp);
tmp=p2;p2=p2->next;free(tmp);
}
}
else if(p1->expn<p2->expn){
p3->next=p1;
p3=p1;
p1=p1->next;
}
else{
p3->next=p2;
p3=p2;
p2=p2->next;
}
}
p3->next=p1?p1:p2;
free(PB);
}
void PrintPolyn(Polynomial &P){
PNode *p;
p=P->next;
while(p!=NULL){
printf("%d*x^%d ",p->coef,p->expn);
p=p->next;
}
}
int main(){
Polynomial PA,PB;
int n,m;
scanf("%d",&n);CreatePolyn(PA,n);
scanf("%d",&m);CreatePolyn(PB,m);
AddPolyn(PA,PB);
PrintPolyn(PA);
return 0;
}