PTA数据结构作业一

6-1 链表的插入算法

本题要求实现一个插入函数,实现在链表llist中的元素x之后插入一个元素y的操作。

函数接口定义:

int InsertPost_link(LinkList llist, DataType x, DataType y); 其中 llist是操作的链表,x是待插入元素y的前驱节点元素,y是待插入的元素

cs 复制代码
int InsertPost_link (LinkList llist,DataType x,DataType y)
{
    LinkList m=llist->next;
    LinkList n;
    while(m->data!=x)
    {
        m=m->next;
        if(m==NULL)
        {
        printf ("not exist data %d\n",x);
            return 0;
        }
    }
    n=(LinkList) malloc (sizeof(struct Node));
        if (n!=NULL)
        {
            n->data=y;
            n->next=m->next;
            m->next=n;
            return 0;
        }
}

6-2 链表的删除算法

本题要求实现一个函数,实现删除链表llist中的指定元素deldata。

函数接口定义:

void DelNode_Link(head, deldata);

其中head是操作的链表表头结点,deldata是待删除的元素。

cs 复制代码
1.创建结构体和宏定义类型名
#include<stdio.h>
#include<stdlib.h>

typedef int DataType;
struct Node {
	DataType	  data;
	struct Node*  next;
};
typedef struct Node  *PNode;
typedef struct Node  *LinkList;

2.创建头节点。
LinkList SetNullList_Link ()
{
    LinkList head=(LinkList)malloc(sizeof(struct Node));
    if(head!=NULL)
    {
       head->next=NULL;
       return head;
    }
    else
    printf("alloc failure");
     return head;
}

3.利用尾插法创建单向链表。
void CreatList(struct Node* head)
{
    int data;
    LinkList p=head->next,pre=head;
    scanf("%d",&data);
    while(data!=-1)
    {
        p=(struct Node*)malloc(sizeof(struct Node));
        p->data=data;
        p->next=NULL;
        pre->next=p;
        pre=p;
        scanf("%d",&data);
    }
}
4.删除值为x的节点。
void DelNode_Link(LinkList head, DataType x)
{
    LinkList p=head->next;
    LinkList beforep=head;  //通过beforep和p遍历整个链表
    while(p!=NULL)
    {
        if(p->data==x)
        {
            beforep->next=p->next;
            free(p);//释放节点p,否则占用内存空间
            break;
        }
        else
        {
            beforep=p;
            p=p->next;
            if(p==NULL)
                printf("not exist %d\n",x);
        }
    }
}

5.打印整个链表。
void print(LinkList head)
{
	LinkList p=head->next;
	while (p!=NULL)
        {
		printf("%d ",p->data);
		p=p->next;
        }
}

6.主函数
int main()
{   int x;
    LinkList head;
    head=SetNullList_Link();
    CreatList(head);
    scanf("%d",&x);
    DelNode_Link(head,x);
    print(head);
    return 0;
}

6-3 移动链表中的最大值到尾部

编写函数MoveMaxToTail(),实现查找单链表中值最大的结点,并将其移动到链表尾部,注意其他结点的相对次序不变。要求尽量具有较高的时间效率。

例如输入8 12 46 30 5,输出为8 12 30 5 46

函数接口定义:

void MoveMaxToTail (LinkList H );

cs 复制代码
void MoveMaxToTail(LinkList head)
{ 
LinkList pre=head;
LinkList r=head;
    LinkList q=pre->next;
    while(q!=NULL)
    { 
        if(pre->data<q->data)
        { 
            pre=q;
        }
            q=q->next;
    }
     while(r->next!=pre)
        r=r->next;      //指针r指向最大元素的上一个元素,便于进行删除操作
    q=head;
    while(q->next!=NULL)
        q=q->next;       //使q重新指向链表中的最后一个元素,便于进行插入操作
    if(pre->next==NULL)
            return;         //若最后一个元素为最大元素,则直接返回,不需要进行其他操作
    else
    { 
     r->next=pre->next;
     pre->next=NULL;
     q->next=pre;
    }
}

6-4 合并两个递增有序的单循环链表

本题要求实现一个合并函数,实现对有序单循环链表tail1和tail2的合并,要求合并时实现去重操作,即合并后的链表中没有重复的元素,并且合并后的链表为递增有序链表。

函数接口定义:

PNode mergeNDeduplicateList(PNode tail1, PNode tail2);

其中tail1是待合并的第一个有序单循环链表,采用的尾指针表示方法;tail2是待合并的第二个有序单循环链表,采用的尾指针表示方法;

解法一:

cs 复制代码
1.创建结构体和宏定义类型名。
#include<stdio.h>
#include<stdlib.h>

typedef int DataType; 
struct Node {
  DataType	  data; 
  struct Node*  next;  
};
typedef struct Node  *PNode;    
typedef struct Node  *LinkList;   

2.创建尾节点,给尾节点的赋值-1。
PNode createEmptyLinkedList()
{
  PNode current;  //尾结点
  current = (PNode)malloc(sizeof(Node));
  current->next = NULL;
  current->data = -1;
  return current;
}

3.创建单循环链表。注意,尾节点并未插入链表中,tail->next指向最后一个节点,并不是tail指向最后一个节点。tail->data的值为-1。
PNode buildCircularLinkedList(int n, PNode tail)
{
	PNode current=NULL, prev;
	prev = tail; 
	for (int i = 0; i < n; i++)
	{
		current = (PNode)malloc(sizeof(Node));
		current->next = NULL;
		scanf("%d", &current->data);
		prev->next = current;
		prev = current;
	}
	current->next = tail->next;     //形成循环
	tail->next = current;     //tail在此时才变成了尾指针,并指向尾结点;之前一直担任头指针的角色,指向的是首元节点。
	return tail;
}

4.实现有序单循环链表tail1和tail2的合并,要求合并时实现去重操作,即合并后的链表中没有重复的元素,并且合并后的链表为递增有序链表。
PNode mergeNDeduplicateList(PNode tail1, PNode tail2)
{
    int temp;
    PNode pre, q;
    //合并tail1和tail2链表,并将循环链表拆成单向链表
    LinkList head=tail1->next->next;        //head为tail1的首元节点
    tail1->next->next= tail2->next->next;    //将tail1的尾结点与tail2的首元节点相连接
    tail2->next->next=NULL;    //将tail2尾结点的指针域置空
    //通过指针pre和p的移动,对链表进行冒泡排序(从小到大)。
    pre=head;         //pre指向首元节点
    q=head->next;
    for(pre=head; pre->next!=NULL; pre=pre->next)
        for(q=pre->next; q!=NULL; q=q->next)
            {
                if(pre->data>q->data)
                {
                    temp=pre->data;
                    pre->data=q->data;
                    q->data=temp;
                }
            }
     //对链表进行去重操作,代码如下
     pre=head;
     q=pre->next;
     while(q!=NULL)
     {
         if(pre->data==q->data)   //两个结点中的数据元素相等
         { 
             if(q== tail2->next)        //当最后两个元素相等时,需要做特殊处理
             {
                tail2->next=pre;          //因为q->next=NULL,当执行pre->next=q->next时,会导致pre->next=NULL,
                pre->next=NULL;      //即tail2节点会丢失,不便于等会链表首尾结合和返回tail2指针
             }                              
              else                                //相等的不是最后两个结点
              {
                 pre->next=q->next;    //删除后一个结点
                 free(q);
                 q=pre->next;
              }
         }
         else    //两个结点中的值不相等,则后移,继续对比
         {
             pre=q;
             q=q->next;
         }
     }
     tail2->next->next=head;  //对链表进行首尾接合,并使tail2作为尾指针
     return tail2;
}
5.打印链表。
void printCircularLinkedList(PNode tail)
{

	PNode current, last;
	last = tail->next;
	current = last->next;
	do
	{
		printf("%d ", current->data);
		current = current->next;
	} while (current != last->next);
}
6.将函数整合进主函数中。代码如下
int main()
{
	PNode list1, list2;
	int list1_number, list2_number;
	list1 = createEmptyLinkedList();
	list2 = createEmptyLinkedList();
	scanf("%d", &list1_number);
	buildCircularLinkedList(list1_number, list1);
	scanf("%d", &list2_number);
	buildCircularLinkedList(list2_number, list2);
	list1 = mergeNDeduplicateList(list1, list2);
	printCircularLinkedList(list1);
	return 0;
}

解法二:

cs 复制代码
#include<stdio.h>
#include<stdlib.h>

typedef int DataType;      
struct Node
{
    DataType data;
    struct Node * next;
};
typedef struct Node Node;  
typedef struct Node  *PNode;
typedef struct Node  *LinkList;

PNode createEmptyLinkedList()
{
    PNode current;
    current = (PNode)malloc(sizeof(Node));
    current->next = NULL;
    current->data = -1;
    return current;
}

PNode buildCircularLinkedList(int n, PNode tail)
{
    PNode current=NULL, prev;
    prev = tail; 
    for (int i = 0; i < n; i++)
    {
        current = (PNode)malloc(sizeof(Node));
        current->next = NULL;
        scanf("%d", &current->data);
        prev->next = current;
        prev = current;
    }
    current->next = tail->next;
    tail->next = current;
    return tail;
}

PNode mergeNDeduplicateList(PNode tail1, PNode tail2)
{
	PNode LinkNode;
	LinkNode = tail2->next->next;
	tail2->next->next = tail1->next->next;
	tail1->next->next = LinkNode;
	free(tail2);
    PNode StopNode,pre,p;
	StopNode = tail1->next->next;
	while(StopNode != tail1->next)
	{
		pre = StopNode;
		p = pre->next;
		while(pre != tail1->next)
		{
			if(p->data == StopNode->data)
			{
				if(p == tail1->next)
				tail1->next = pre;
				PNode temp;
				temp = p;
				pre->next = p->next;
				p = pre->next;
				free(temp);
			}
			else
			{
				pre = pre->next;
				p = pre->next;
			}
		}
		StopNode = StopNode->next;
	}
    do
	{
		pre = tail1->next->next;
		p = pre->next;
		while(pre != tail1->next)
		{
			if(p->data < pre->data)
			{
				DataType TempData;
				TempData = p->data;
				p->data = pre->data;
				pre->data = TempData; 
			}
			else
			{
				pre = pre->next;
				p = pre->next;
			}
		}
		StopNode = StopNode->next;
	}
	while(StopNode != tail1->next);
	return tail1;
}

void printCircularLinkedList(PNode tail) 
{
    PNode current, last;
    last = tail->next;
    current = last->next;
    do
    {
        printf("%d ", current->data);
        current = current->next;
    } while (current != last->next);
}

int main()
{
    PNode list1, list2;
    int list1_number, list2_number;
    list1 = createEmptyLinkedList();
    list2 = createEmptyLinkedList();
    scanf("%d", &list1_number);
    buildCircularLinkedList(list1_number, list1);
    scanf("%d", &list2_number);
    buildCircularLinkedList(list2_number, list2);
    list1 = mergeNDeduplicateList(list1, list2);
    printCircularLinkedList(list1);
    return 0;
}

6-5 链表中奇偶结点的移动

本题要求实现一个函数,实现对单循环链表中奇数和偶数结点的移动,要求奇数在前面,偶数在后面,且结点之间的相对顺序不变。

函数接口定义:

PNode Move_Odd_Even(LinkList tail);

tail是单循环链表的尾指针

解法一:

奇偶点移动函数,此函数是本题的重点,采用的方法大致为:

①建立两个新链表,head1链表负责装偶数,head2链表负责装奇数。

②遍历链表每一个节点,若为奇数,则利用尾插法插入head2链表;若为偶数,则利用尾插法插入head1链表;

③将head1和head2的链表头尾连接,形成一个新的单向循环链表,并将次链表的尾指针作为返回值。

cs 复制代码
PNode  Move_Odd_Even(LinkList tail)
{
   PNode head=tail->next, pre=head->next, q=pre->next;
   free(head);    //释放原链表的头指针,因为头指针无数据
   LinkList head1=(LinkList)malloc(sizeof(struct Node));
        PNode pre1=head1;    //pre1指针随着新插入的节点移动,便于进行尾插法
   LinkList head2=(LinkList)malloc(sizeof(struct Node));
        PNode pre2=head2;    //pre2指针随着新插入的节点移动,便于进行尾插法
   while(q!=head->next)    //原链表是循环链表,当q遍历到原来pre的位置(首元节点)时,遍历结束
   {
       if (pre->data%2==0)    //判断元素是否为偶数
       {
           pre->next=pre1->next;
           pre1->next=pre;
           pre1=pre1->next;
       }
       else    //若不是偶数,则为奇数
       {
           pre->next=pre2->next;
           pre2->next=pre;
           pre2=pre2->next;
       }
       pre=q;
       q=q->next;     //pre始终保持在q的前面
   }
//将head1链表和head2链表合成一个新的单循坏链表
   head1=head1->next;  //head1链表在后,不需要其头结点
   pre2->next=head1;    //两个链表相连接
   pre1->next=head2;    //形成循坏
   return pre1;               //返回新循坏链表的尾指针
}

解法二:

该程序的主要思想在于:

1、遍历栈,找到偶数

2、利用尾插法将偶数插入队尾

cs 复制代码
#include<stdio.h>
#include<stdlib.h>

typedef int DataType; 
struct Node 
{
    DataType      data; 
    struct Node*  next;  
};
typedef struct Node  *PNode;    
typedef struct Node  *LinkList;   

LinkList CreateList_Tail_loop()
{
    LinkList head = (LinkList)malloc(sizeof(struct Node));
    PNode cur = NULL;
    PNode tail = head;
    DataType data;
    scanf_s("%d", &data);
    while (data != -1)
    {   
        cur = (struct Node*)malloc(sizeof(struct Node));
        cur->data = data;
        tail->next = cur;
        tail = cur;
        scanf_s("%d", &data);
    }
    tail->next = head;
    return tail;
}
PNode  Move_Odd_Even(LinkList tail)
{
	PNode pre = tail->next;
	PNode head = tail->next;
	PNode P2 = NULL;
	PNode p = pre->next;
	PNode temp = (struct Node*)malloc(sizeof(struct Node));
	temp->data = 0;
	tail->next = temp;
	temp->next = head;
	tail = temp;
	while(p->data)
    {
        if(p->data%2 ==0)
        {
            P2 = p;
            p = p->next;
            pre->next = p;
            tail->next = P2;
            tail = P2;
        }
        else
        {   p = p->next;
            pre = pre->next;}
    }
    pre->next = temp->next;
    tail->next = head;
    free(temp);
    return tail;
}

void print(LinkList tail)    
{
    PNode  head = tail->next;
    PNode p = head->next;
    while (p != head)
    {
        printf("%d ", p->data);
        p = p->next;
    }
}

void DestoryList_Link(LinkList tail)
{
    PNode pre = tail->next;
    PNode p = pre->next;
    while (p != tail)
    {
        free(pre);
        pre = p;
        p = pre->next;
    }
    free(pre);
    free(tail);
}

int main()
{
    LinkList tail = NULL;
    LinkList p = NULL;
    tail = CreateList_Tail_loop();
    p = Move_Odd_Even(tail);
    print(p);
    DestoryList_Link(tail);
    return 0;
}

7-1 多项式的加法

用链表表示多项式,并实现多项式的加法运算

输入格式:

输入在第一行给出第一个多项式POLYA的系数和指数,并以0,0 结束第一个多项式的输入;在第二行出第一个多项式POLYB的系数和指数,并以0,0 结束第一个多项式的输入。

输出格式:

对每一组输入,在一行中输出POLYA+POLYB和多项式的系数和指数。

输入样例:

5,0 2,1 1,6 8,15 0,0
-2,1 3,6 4,8 0,0

输出样例:

5,0 4,6 4,8 8,15 

解法一:

cs 复制代码
本题主要思路:
1.建立两个头指针分别为head1和head2链表,链表每一个节点分别记录每一个多项式的系数coef和指数exp。
2.preA遍历链表head1,preB遍历链表head2。
3.建立一个只有一个头节点的链表head,逐步遍历链表head1和head2。分别有如下三种情况:
①preA->exp<preB->exp,将节点preA利用尾插法插入链表head。
②preB->exp<preA->exp,将节点preB利用尾插法插入链表head。
③preB->exp=preA->exp,这种情况分为两种:
当preA->coef+preB->coef=0时,释放节点preA和preB。
当preA->coef+preB->coef≠0时:将多项式指数相同的项的系数相加,记录在preA,并利用尾插法将preA节点插如链表head。
#include<stdio.h>
#include<stdlib.h>
struct tagNode
{
	float coef;     //系数coefficient
	int exp;         //指数exponent
	struct tagNode *next;  //指针域 
};

typedef struct tagNode Node;
typedef struct tagNode *PNode;

void insertList(PNode head,PNode pnode)
{
	PNode pPre = head;
	while(pPre->next != NULL)
	{
		if(pPre->next->exp>pnode->exp)   //链表中节点pPre->next的指数>新加入节点pnode的指数
		{                                                       //将新节点pnode插入到pPre之后
			pnode->next = pPre->next;
			pPre->next = pnode;
			break;
		}
		else     //链表中节点pPre->next的指数≤新加入节点pnode的指数,继续往后查找
		{
			pPre = pPre->next;
		}
	}
	if(pPre->next == NULL)     //新加入节点pnode的指数较大,放在链表最后
	{
		pPre->next = pnode;
	}
}
 
void CreateList(PNode head)
{
	int exp;
	float coef;
	PNode pTemp = NULL;
	head->next = NULL;
	scanf("%f,%d",&coef,&exp);
	while(coef != 0 || exp != 0)
	{
		pTemp = (PNode)malloc(sizeof(struct tagNode));
		pTemp->coef = coef;
		pTemp->exp = exp;
		pTemp->next = NULL;
		insertList(head, pTemp);
		scanf("%f, %d", &coef, &exp);
	}
}
 
void printLinkedList(PNode head)
{
	PNode temp = head->next;
	while(temp != NULL)
	{
		printf("%0.0f,",temp->coef);
		printf("%d ",temp->exp);
		temp = temp->next;
	}
	printf("\n");
}
 
void Add_Poly(PNode pa,PNode pb)
{
	PNode p = pa->next;    //链表1,和多项式的结果放在链表1中 
	PNode q = pb->next;
	PNode pre = pa;
	PNode u;
	float x;        //临时变量 
	while(p != NULL && q != NULL)
	{
		if(p->exp < q->exp)  //比较链表1和链表2当前节点的指数大小,链表1也是存放结果的地方
		{
			pre = p;
			p = p->next; //p指向要比较的下一个节点,pre最终指向结果链表的最后一个节点
		}
		else if(p->exp == q->exp) //假如链表1和链表2的指数相等,则要系数相加
		{
			x = p->coef + q->coef;
			if(x != 0) //相加后的系数不是0,保留上一个节点就好了
			{
				p->coef = x;
				pre = p; 
			 } 
			 else    //相加后系数为0,不需要保留任何一个节点,删除链表1的节点
			 {
				 pre->next = p->next;
				 free(p); 
			 }
			 p=pre->next;     //p指向下一个节点
			 
			 //下面是进行链表2的删除工作
			 u = q;
			 q = q->next;
			 free(u); 
		}
		else  //如果链表2当前节点指数小,把链表2的当前节点加入到链表1中
		{
			u = q->next;
			q->next = p;
			pre->next = q;
			pre = q;
			q = u; 
		}
	}
	if(q)        //如果链表2比链表1长,需要把链表2多余的部分加入到结果链表中;
//如果链表1比链表2长则不需要任何操作。
	{
		pre->next = q; 
	}
	free(pb);
}	
	
int main()
{
	PNode head1 = (PNode)malloc(sizeof(struct tagNode));
	PNode head2 = (PNode)malloc(sizeof(struct tagNode));
	CreateList(head1);
	CreateList(head2);
	Add_Poly(head1,head2);
	printLinkedList(head1);
	return 0;
}

解法二:

cs 复制代码
本题主要思路:
1.建立两个头指针分别为head1和head2链表,链表每一个节点分别记录每一个多项式的系数coef和指数exp。
2.preA遍历链表head1,preB遍历链表head2。
3.建立一个只有一个头节点的链表head,逐步遍历链表head1和head2。分别有如下三种情况:
①preA->exp<preB->exp,将节点preA利用尾插法插入链表head。
②preB->exp<preA->exp,将节点preB利用尾插法插入链表head。
③preB->exp=preA->exp,这种情况分为两种:
当preA->coef+preB->coef=0时,释放节点preA和preB。
当preA->coef+preB->coef≠0时:将多项式指数相同的项的系数相加,记录在preA,并利用尾插法将preA节点插如链表head。
#include<stdio.h>
#include<stdlib.h>

typedef int DataType; 
struct Node
{
	DataType	  dataX,dataY;  
	struct Node*  next;  
};
typedef struct Node  *PNode;     
typedef struct Node  *LinkList;  

LinkList SetNullList_Link() 
{
	LinkList head = (LinkList)malloc(sizeof(struct Node));
	if (head != NULL)
	head->next = NULL;
	else
	printf("alloc failure");
	return head; 
}

void CreateList(struct Node* head)
{
	PNode p = NULL; 
	PNode q = head;
	int dataX,dataY;
	scanf("%d,%d", &dataX,&dataY);
	while (dataX != 0 || dataY != 0) 
	{   
		p = (struct Node*)malloc(sizeof(struct Node));
		p->dataX = dataX;
		p->dataY = dataY;
		p->next = NULL;
		q->next = p;
		q = p;
		scanf("%d,%d", &dataX,&dataY);
	}
}

PNode mergeNDeduplicateList(PNode POLYA, PNode POLYB)
{
	PNode A,B,pre;
	B = POLYB->next;
	while(B != NULL)
	 {
	 	pre = POLYA;
	 	A = pre->next;
	 	while(A != NULL)
	 	{
	 		if(A->dataY == B->dataY)
	 		{
	 			A->dataX = A->dataX + B->dataX;
	 			if(A->dataX == 0)
	 			{
	 				pre->next = A->next;
	 				free(A);
				 }
	 			POLYB->next = B->next;
	 			free(B);
	 			B = POLYB->next;
	 			break;
			 }
			 else if(A->dataY > B->dataY)
			 {
			 	POLYB->next = B->next;
			 	B->next = A;
			 	pre->next = B;
			 	B = POLYB->next;
			 	break;
			 }
			 pre = pre->next;
			 A = pre->next;
		 }
	 }
    PNode StopNode;
	 StopNode = POLYA;
	 while(StopNode != NULL)
	{
		pre = POLYA;
		A = pre->next;
		while(A->next != NULL)
		{
			if(A->dataY > A->next->dataY)
			{
				pre->next = A->next;
				PNode temp;
				temp = A->next;
				A->next = temp->next;
				temp->next = A;
			}
			pre = pre->next;
			A = pre->next;
		}
		StopNode = StopNode->next;
	}
	 return POLYA;
}

void print(LinkList head)    
{
	PNode p = head->next;
	while (p != NULL)
	{
		printf("%d,%d ", p->dataX,p->dataY);
		p = p->next;
	}
}

void DestoryList_Link(LinkList head)
{
	PNode  pre = head; PNode p = pre->next;
	while (p) 
	{
		free(pre);
		pre = p;
		p = pre->next;
	}
	free(pre);
}

int main()
{
	LinkList POLYA,POLYB;
	POLYA = SetNullList_Link();
	POLYB = SetNullList_Link();
	CreateList(POLYA);
	CreateList(POLYB);
	POLYA = mergeNDeduplicateList(POLYA,POLYB);
	print(POLYA);
	DestoryList_Link(POLYA);
	return 0;
}
相关推荐
XLYcmy2 小时前
分布式练手:Server
c++·windows·分布式·网络安全·操作系统·c·实验源码
学习前端的小z1 天前
【C++】B2089 数组逆序重存放
c
charlie1145141912 天前
如何使用 OpenCV 扫描图像、查找表和时间测量
c++·opencv·学习·计算机视觉·c·教程
charlie1145141912 天前
Linux Kernel Programming4
linux·c·makefile·内核开发·内核日志
学习前端的小z3 天前
【C++】2029:【例4.15】水仙花数
c
学习前端的小z3 天前
【C++】探索一维数组:从基础到深入剖析
c
oioihoii3 天前
VSCode下配置Blazor环境 & 断点调试Blazor项目
ide·python·c
charlie1145141914 天前
从0开始的Opencv之旅(到尝试构建一个图像编辑器):0,opencv demo
c++·图像处理·opencv·学习·c·教程
这题怎么做?!?5 天前
const与constexpr
c++·c