目录
链表的合并
链表的结点逆置
顺序表的高效划分
链表的合并
已知两个递增有序的单链表A和B,分别表示两个集合。试设计一个算法,用于求出A与B的交集,并存储在C链表中。例如 : La = {2,4,6,8};Lb = {4,6,8,10};Lc = {4,6,8}。(要求上机实现完整程序代码、核心代码有注释,有运行结果)。
算法分析:遍历这两个链表A和B,使用两个指针,创建一个新的空链表C,然后比较当前节点的数据,如果相等,则将该数据添加到链表C中,然后同时移动两个链表的指针。如果不相等,则移动较小值所在链表的指针。这样可以确保只添加两个链表中共有的元素到链表C中。
#include <stdio.h>
#include <malloc.h>
typedef int ElemType;
typedef struct LNode
{ElemType data;struct LNode *next; //指向后继结点
} LinkNode; //创建单链表,头插法
LinkNode * createlist(int a[],int len) {//len是链表的长度LinkNode * L;LinkNode * s;L = (LinkNode *)malloc(sizeof(LinkNode));L -> next = NULL;//创建头结点,next指向为空for(int i = 0; i < len; i++) {s = (LinkNode*)malloc(sizeof(LinkNode));//创建结点ss -> data = a[i];s -> next = L -> next; //将s插入原首节点前,头结点后L -> next = s;}return L;
}//用于打印链表
//由于存储链表使用的是头插法,所以打印时我们现将链表存入一个数组
//再将那个数组反向输出就是我们需要的样子
void printlist(LinkNode *L) {LinkNode *p = L -> next;//让p指向首结点int arr[4];int len = 0,i = 0;while(p != NULL) {arr[i] = p -> data;p = p -> next;i++,len++;//只要没到尾结点就一直存入arr数组}len = len - 1;//最后多加了一次len所以要减去for(int i = len; i >= 0; i--) {printf("%d ",arr[i]);}printf("\n");
}//求两个链表的交集
LinkNode * intersection(LinkNode *a,LinkNode *b) {//传入a,b两个链表LinkNode *c;c = (LinkNode *)malloc(sizeof(LinkNode));LinkNode *r = c;//创建链表c的头结点,使用尾插法a = a -> next,b = b -> next;//让链表a和链表b指向它们的首结点LinkNode *p;while(a != NULL && b != NULL) {if(a -> data == b -> data) {//若二值相等,使用尾插法存入c中,并且让这两个指针都往后移动p = (LinkNode *)malloc(sizeof(LinkNode));p -> data = a -> data;r -> next = p;r = r -> next;a = a -> next,b = b -> next;}else {//由于创建列表时使用了尾插法,所以要变得相反//若二值不相等则值更大的往后移一格if(a -> data > b -> data)a = a -> next;if(b -> next > a -> next)b = b -> next;}}r -> next = NULL;//尾插法注意要让尾结点的next域置为空return c;
}int main() {//创建链表aint a[4];a[0] = 2,a[1] = 4,a[2] = 6,a[3] = 8;LinkNode *la;la = createlist(a,4);printf("链表a为:");printlist(la);//创建链表bint b[4];b[0] = 4,b[1] = 6,b[2] = 8,b[3] = 10;LinkNode *lb;lb = createlist(b,4);printf("链表b为:");printlist(lb);//得到链表la和lb的交集lcLinkNode *lc = intersection(la,lb);printf("链表a和链表b的交集链表c为:");printlist(lc);
}
链表的结点逆置
假设有一个带头结点的单链表L=(2,4,6…,20)。设计一个算法将所有结点逆置,即:L=(20,18,…,2)。(要求要求上机实现完整程序代码、核心代码有注释,有运行结果)
算法分析:可以使用尾插法建立第一个链表,再写一个逆置函数,传入这个链表,在函数里面改变当前节点的指针使其指向其前一个节点,以此类推,直到遍历完所有的节点。
#include <stdio.h>
#include <malloc.h>
typedef int ElemType;
typedef struct LNode
{ElemType data;struct LNode *next; //指向后继结点
} LinkNode; //创建单链表,尾插法
LinkNode * createlist(int a[],int len) {LinkNode *L,*r,*s;L = (LinkNode*)malloc(sizeof(LinkNode));//L为头结点r = L;for(int i = 0; i < len; i++) {s = (LinkNode *)malloc(sizeof(LinkNode));s -> data = a[i];r -> next = s;r = r -> next;//将数据存入s中并且让r的next指向它//再将r向后移动一格}r -> next = NULL;//记得要让尾结点的next域为空return L;
}//打印单链表
void printlist(LinkNode * l) {l = l -> next;//让l指向它的首结点while(l != NULL) {printf("%d ",l -> data);l = l -> next;}printf("\n");
}//打印逆置后的单链表
void printreverselist(LinkNode *l) {//采用这种逆置方法后不用指向首结点,此时l即为首结点while(l != NULL) {printf("%d ",l -> data);l = l -> next;}printf("\n");
}//逆置链表函数
LinkNode * reverselist(LinkNode * head) {//创建新的头结点pLinkNode *p;LinkNode *l,*r;l = head -> next;//l表示left,是左边的指针//r表示right,是右边的指针//让s指向首结点,头结点的next指向空head -> next = NULL;//核心代码while(l != NULL) {r = l -> next;//保存当前节点的下一个节点l -> next = p;//将当前节点的next指向前一个节点p = l;//更新p为当前节点l = r;//移动到下一个节点}return p;
}int main() {//创建逆置前的链表int a[100];int n = 1;for(int i = 0; i < 10; i++) {a[i] = 2 * n;n++;}LinkNode *l = createlist(a,10);printf("逆置前的链表为:");printlist(l);//逆置链表l = reverselist(l);printf("逆置后的链表为:");printreverselist(l);
}
顺序表的高效划分
对有n个整形元素的顺序表以第一个元素为基准进行高效划分,将所有大于该基准的所有元素放在该基准的右边;将所有小于等于该基准的所有元素放在该基准的左边。例如对于线性表(17,2,3,5,4,20,1,18,19,20,21,6,22)要求要求上机实现完整程序代码、核心代码有注释,有运行结果)
#include <stdio.h>
#include <malloc.h>
#define MaxSize 50
typedef int ElemType;
typedef struct
{ int data[MaxSize]; //存放顺序表元素int length; //存放顺序表的长度
} SqList; //顺序表的类型//建立顺序表
SqList * createlist(int a[],int len) {SqList *l;l = (SqList *)malloc(sizeof(SqList));int k = 0;//k用于记录顺序表的长度for(int i = 0; i < len; i++) {l -> data[i] = a[i];k++;}l -> length = k;return l;
}void partitionlist(SqList * list) {int l = 0,r = list -> length - 1;//让l指向头,r指向尾int base = list -> data[0];//将第一个数设置为基准while(l < r) {while(r > l && list -> data[r] > base)r--;//先从右往左遍历,找到第一个小于等于base的数list -> data[l] = list -> data[r];//将这个数放入l的位置上while(l < r && list -> data[l] <= base)l++;//再从左往右,找到第一个大于base的数list -> data[r] = list -> data[l];//将这个数放在r的位置上}list -> data[l] = base;//最后把这个数放在位置l处
}//打印顺序表
void printlist(SqList *l) {for(int i = 0; i < l -> length; i++) {printf("%d ",l -> data[i]);}printf("\n");
}int main() {//创建顺序表int arr[100];arr[0] = 17;arr[1] = 2;arr[2] = 3;arr[3] = 5;arr[4] = 4;arr[5] = 20;arr[6] = 1;arr[7] = 18;arr[8] = 19;arr[9] = 20;arr[10] = 21;arr[11] = 6;arr[12] = 22;SqList *l;l = createlist(arr,13);printf("初始的顺序表为:");printlist(l);//进行高效划分partitionlist(l);printf("高效划分后的顺序表为:");printlist(l);}