数据结构之线性表
一、线性表
双链表删除元素
删除元素和 增加元素的大忌就是导致引用连断链
s->next = p->next;
s->prior = p;
p->next = s;
s->next->prior = s;
双链表删除元素
s->prior->next = s->next;
s->next->prior = s-prior;
free(s);//记住删除元素后要释放这个元素
静态链表节点类型定义
静态链表可以理解为数组
typedef struct{
int data;
int next;
}SLNode;
顺序表的插入删除
//建表
int sqList[maxSize] = {1,2,3,...,n}
int length = n;
/* sqList是待插入的数组,length是数组大小,因为需要改变大小,所以这里是引用类型
* p表示往哪里插,也就是位置,e表示元素
*/
int insertElem(int sqList[],int &length,int p,int e){
if(p<0||p>length){
return 0;//插入位置不合理
}
//元素分别后移
for(int i = length-1;i>p;--i){
sqList[i+1] = sqList[i]
}
//插入数据,长度+1
sqList[p] = e;
++length;
return 1;//返回1表示插入成功
}
//与插入不同的参数是e,一般要拿到删除元素的值,所以需要引用值
int deleteElem(int sqList,int &length,int p;int &e){
if(p<0||p>length-1){
return 0;
}
e = sqList[p];
for(int i=p;i<length-1;++i){
sqList[i] = sqList[i+1];
}
--length;
return 1;
}
//尾插法
void createLinkListR(LNode *&head){
head = (LNode *)malloc(sizeof(LNonde));
head->next = NULL;
LNode *p = NULL,*r = head;
int n;
std::cin>>n;//scanf("%d",&a)
for(int i=0;i<n;++i){
std::cin>>p->data;//scanf("%d",&(p->data));
p->next = r->next;
r->next = p;
r = p;
}
}
//头插法
void createLinkListH(LNode *&head){
head = (LNode *)malloc(sizeof(LNode));
head->next = NULL;
LNode *p = NULL;
int n;
std::cin>>n;//scanf("%d",&n);
for(int i=0;i<n;i++){
p = (LNode *)malloc(sizeof(LNode));
p->next = NULL;
std::cin>>p->data;//scanf("%d",&(p->data));
p->next = head->next;
head->next = p;
}
}
- 真题解答
键盘输入n个英文字母,输入格式为 n、C1、C2、…、 Cn,其中n表示字母的个数。请编程以这些输入数据建立一个单链表,并要求将字母不重复的存入链表。
void createLinkNoSameElem(LNode *&head){
head = (LNode *)malloc(sizeof(LNode));
head->next = NULL;
LNode *p;
int n;
char ch;
std::cin>>n;
for(int i=0;i<n;i++){
std::cin>>ch;
p = head->next;
while(p!=NULL){
//如果找到一个值,这个值相等,就要跳出循环
if(p->data==ch)
break;
//不相等就继续遍历
p = p->next;
}
//遍历 如果找到相同的p!=NULL,如果没找到相同的,那么p就不为空
if(p==NULL){
p = (LNode *)malloc(sizeof(LNode));
p->data = ch;
p->next = head->next;//这里说明是头插法
head->next = p;
}
}
}
逆置问题
-
顺序表的逆置
for(int i = left,j = right;i<j;++i,--j){ temp = a[i]; a[i] = a[j]; a[j] = temp; }
-
链表的逆置
while(p->next != q){ t = p->next; p->next = t->next; t->next = q->next; q->next = t; }
-
真题解答
- 将一段长度为n的数组的前端k(k<n)个元素逆序后移动到数组后段,要求原数组中的元素不丢失;
void reverse(int a[], int left,int right,int k){ int temp; //当k大于表长的一半,就需要设置i<left-k for(int i = left,j=right;i<left-k&&i<j;++i,--j){ temp = a[i]; a[i] = a[j]; a[j] = temp; } }
- 将一段长度为n的数组的前端k(k<n)个元素保持原序移动到数组后段,要求原数组中的元素不丢失;
void moveToEnd(int a[],int n,int k){ reverse(a,0,k-1,k); reverse(a,0,n-1,k); }
3),将数组中的元素(X0, X1…Xn-1),经过移动后变为(Xp,Xp+1,X)
void moveP(int a[],int n,int p){ reverse(a,0,p-1,p); reverse(a,p,p-1,n-p); reverse(a,0,n-1,n) }
取最值问题
- 顺序表取最值
int max = a[0];
int maxIdx = 0;
for(int i=0;i<n;++i){
if(max<a[i]){
max = a[i];
maxIdex = i;
}
}
//当然取最小值同理,这里就不写了
-
链表取最值
LNode *p,*q; int min = head->next->data; q = p = head->next; while(p!=NULL){ if(min>p->data){ min = p->data; q = p; } p = p->next; } //双链表的最值问题 void maxFirst(DLNode *head){ DLNode *p = head->rlink,*q =p; int max = p->data; while(p!=NULL){ if(max<p->data){ max = p->data; q = p; } p = p->rlink; } //删除找到的节点 DLNode *l = q->llink;//左节点 *r = q->rlink;//右节点 l->rlink = r;//左节点指向右节点 if(r!=NULL)//双链表,当最后一个节点的值为null的时候,就不需要将右边指向左边了 r->llink =l; //插入操作,也就是插入到头结点之后 q->llink = head; q->rlink = head->next; head->rlink = q; q->rlink->llink = q; }
归并操作(顺序表)
void mergearray(int a [],int m,int b[],int n,int c[]){
int i = 0,j = 0;
int k = 0;
while(i<m&&j<n){
if(a[i]<b[j]){
c[k++] = a[i++];//c[k] = a[i];k++;i++;
}else{
c[k++] = b[j++];//c[k] = b[j];k++;j++;
}
}
while(i<m){
c[k++] = a[i++];
}
while(j<n){
c[k++] = b[j++];
}
}
归并操作(链表)
void merge(LNode *A, LNode *B, LNode *&C){
LNode *p = A->next;
LNode *q = B->next;
LNode *r;
C = A ;
C->next = NULL;
free(B);
r = C;
while(p != NULL && q !=NULL){
if(p->data <= q->data){
r->next = p;
r = r->next;
}else{
r->next = q;
r = r->next;
}
}
if(p!=NULL) r->next = p;
if(q!=NULL) r->next = q;
}
//如果是想逆序,倒着插入 就可以了
//归并操作实现一条逆序序列的代码
void mergeR(LNode *A, LNode *B,LNode *&C){
LNode *p = A->next;
LNode *q = B->next;
LNode *s;
C = A;
free(B);
while(p!=NULL&&q!=NULL){
if(p->data <= q->data){
s = p;
p = p->next;
s ->next = C->next;
C->next = s;
}else{//p->data >= q->data
s = q;
q = q->next;
s->next = C->next;
C->next = s;
}
}
while(p!=NULL){
s = q;
q = q->next;
s->next = C->next;
C->next = s;
}
while(q!=NULL){
s = p;
p = p->next;
s->next = C->next;
C->next = s;
}
}
划分
这里需要提一点就是,在线性表的划分当中经常会出现枢轴这类的问题,也就是谁在枢轴的坐标都是小于枢轴的,枢轴的右边都是大于数轴的,但是具体得看题目怎么说了
void partition(int arr[], int n){
int temp;
int i = 0;
int j = n-1;
while(i<j){
while(i<j&&arr[j]>==temp) --j;
if(i<j){
arr[i] = arr[j];
++i;
}
while(i<j&&arr[i]<temp) --i;
if(i<j){
arr[j] = arr[i];
--j;
}
}
arr[i] = temp;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)