【考研】顺序表与链表

顺序表结构


顺序存储的静态分配

#define MaxSize 50//定义线性表的最大长度
typedef int Elemtype//假定表中元素类型是int
typedef struct{
	ElemType data[MaxSize];//顺序表的元素(数组)
	int length ;//顺序表的当前长度
}

顺序存储的动态分配

typedef int Elemtype
typedef struct 
{
	ElemType *data ;//指示动态分配数组的指针 
	int MaxSize , length ;//数组的最大容量和当前个数
};

/* c语言的动态分配语句 */
#define InitSize 100
SeqList L;
L.data=(ElemType*)malloc(sizeof(ElemType)*InitSzie);

链表


结点结构


单链表

typedef struct LNode{
	ElemType data ;//数据域 
	struct LNode *next; //指针域		
}LNode , *LinkList;

双链表

typedef struct DNode{
	ElemType data;
	struct DNode *prior , *next;
}DNode , *DinkList;

静态链表

#define MaxSize 50	//定义链表最大长度	
typedef struct{		//静态链表结构类型的定义
	ElemType data;	//存放数据结构
	int next;		//存放元素的数组下标
}SlinkList[MaxSize];

输出链表中的值:

printf(p->next->data);

声明

声明链表:LinkList &A
声明结点/指针:LNode *p

链表的创建


头插法

LinkList List_HeadList(LinkList &L){
	LNode *p , int x;
	L = (LinkList *)malloc(sizeof(LinkList));	//申请空间
    L->next = NULL;			//指向为NULL
    scanf("%d" , &x);		//输入x值
    while(x != 999){
    	p = (LinkList*)malloc(sizeof(LinkList));
    	p->data = x;
    	p->next = L->next;
    	L->next = p;
    	scanf("%d" , &x);
    }
	return L;
}

尾插法

LinkList CreatLinkList(LinkList &L){
	int x ;
	L=(LinkList)malloc(sizeof(LNode));
	LNode *s , *r = L; //r为表尾指针 指向表尾 
	scanf("%d" , x) ; //输入结点的值 
	while(x != 9999){//输入9999表示结束 
		s=(LNode*)malloc(sizeof(LNode)) ;
		s->data = x ;
		r->next = s ;
		r= s ;//r指向新的表尾结点 
		scanf("%d" , x) ;
	}
	r->next = NULL ;//尾结点指针置空 
	return L;

顺序表算法


从顺序表中删除最小值

并由函数返回被删元素的位置,空出位置由最后一个元素补上

void DeleteElem_min( SqList &L , int minvalue , int k){
//先查找出最小值 
	if(L.length == 0)
		return 1;
	minvalue = L.data[0];	//先设最小值为数组0
	int k=0;	//初始位置为0 
	for( int i = 1 ; i < L.length ; i++){
		if( minvalue > L.data[i] ){
			minvalue = L.data[i];
			k = i;
		}
	} 
	L.data[k] = L.data[L.length-1];	
	L.length--;
	return k;
}  

顺序表L逆置

/顺序表L逆置 
void Reverse(SqList &L){
	int temp;	//辅助变量
	for( int i = 0 ; i < L.length/2 ; i++){
		temp = L.data[i];
		L.data[i] = L.data[L.length-i-1];
		L.data[L.length-i-1] = temp;
	} 
	return 0;
}

删除所有值为x的数据元素

void Delete_key( SqList &L ,int key ){
	int k = 0;
	for( int i = 0 ; i < L.length ; i++ ){
		if( L.data[k] != key){
			L.data[k] = L.data[i];
			k++; 
		}
	}
	L.length = k;
	return L.length;
}

删除有序表区间为【s,t】之间的数据元素

有序表

bool Delete_rangekey(SqList &L , int key ,int s ,int t) {
//基于L为有序表,则用ij找到大于s和小于t的值	
	int i,j; 
	if( s >= t || L.length == 0)
		return false;
	for(i = 0 ; L.data[i] < s && i < L.length ; i++ );
	if( i >= L.length )
		return false;
	for( j=i ; L.data[j] <= t && j <= L.length ; j++ );
	for( ; j < L.length ; i++,j++);
		L.data[i] = L.data[j];
	L.length= i;
	return true;
}

删除顺序表区间为【s,t】之间的数据元素

bool Del_s_t(SqLsit &L , int s ,int t){
	int i , k =0;
	if( L.length == 0 || s>= t)
		return false;
	for( i = 0 ; i < L.length ; i++ ){
		if( L.data[i] >= s && L.data[i] <= t)
			k++;
		L.data[i-k] = L.data[i];	//前移k个位置 
	}
	L.length -= k;
	return true;	
}

删除有序表中重复的值

bool Delete_data( SqList &L , int key ){
	int i ,j;
	if(L.length == 0 )
		return true;
	for(i = 0 j=1; j < L.length ; j++){
		if(L.data[i] != L.data[j])
			L.data[++i] = L.data[j];
	}
	L.length = i+1;
	return true; 		
} 

合并两个有序表

int MergeList_two(SqList &L1 , SqList &L2 , SqList &L3 ){
//将有序表L1,L2 , 比较算法
	int i=0 , j=0 ,k=0;
	if( L1.length + L2.length > L3.length)
		return false;	
	while( i < L1.length && j < L2.length ){
		if(L1.data[i] > L2.data[j])
			L3.data[k] = L2.data[j];   
		else
			L3.data[k] = L1.data[i];
	}
	while( i < L1.length)
		L3.data[k++] = L1.data[i++];
	while( j < L2.length)
		L3.data[k++] = L2.data[i++];
	L3.length= k;
	return true; 
}

置换算法

//置换算法
//思路(折半排序):分三次进行 
//将an和bn互换,再各自内部在进行一次折半查找 
void Search_two( int A[] , int left ,int right , int arraySize ){	
//arraySize代表A【】的长度,做一个标记,证明right没有超过上限,默认m+n 
	int temp;
	if(right >= left || right >= arraySiz)
		return;
	int mid = (left + right)/2;
	for(int i = 0 ; i <= mid-left ; i++){
		temp = A[left+i];
		A[left+i] = A[right-i];
		A[right-i] = temp;
	}
} 

void ExChange( int A[] , int m , int n , int mid , arraySize){
	Search_two(A , 0 , m+n-1 , arraySize);
	Search_two(A , 0 , n-1 , arraySize);
	Search_two(A , n , m+n-1 , arraySize);
}

数组中ab部分变成ba部分

//数组向左移动p个位置 
//ab变成ba,用逆置的思想来做 
void Reverse_elem_p(int A[] , int left ,int right){
	if(left <= right )
		return;
	for( int i = 0 ; i < right-left ; i++){
		int temp = A[left+i];
		A[left+i] = A[right-i];
		A[right-i] = temp;
	}
}

void ALL_Reverse( int A[] , int int p , int n){
	Reverse_elem_p(A , 0 , n-1);
	Reverse_elem_p(A , 0 , P-1);
	Reverse_elem_p(a , p , n-1);
}

数组种查找重复的元素(主元素)

//主元素必须满足是重复数最多的,且x要大于n/2
int Majority( int A[] , int n){
	int i , c , count=1;
	c = A[0];
	for( i =1 ; i < n ; i++){
		if(A[i] == c)
			count++;
		else{
			if(count > 0)
				count--;
			else{		//更换候选主元素的实际出现次数 
				c = A[i];
				count =1;
			}
		}
	} 
	if(count > 0 ){
		for(i = count = 0 ; i < n ; i++){
			if(A[i] == c)
				count++;	//统计主元素出现的次数 
		}
	}
	if(count > n/2)
		return c;	//却仍候选元素 
	else	
		return -1;	//不存在主元素 
}

寻找最小正整数

//最小正整数,从1,2,3,4开始找数组中的没有出现过的数
void findMissMId( int A[] , int n){
	int *B =(int *)malloc(n*sizeof(int ));
	memset(B , 0 , sizeof(int)*n);		//赋初值为0
	for( int i=0 ; i < n ;i++){
		if(A[i] > 0 && A[i] < n)
			B[A[i]-1] = 1;
	}
	for(int i = 0 ; i < n ; i++){		//扫描数组B,找到目标值
		if(B[i] == 0)
			breal;
	}
	return i+1;
	
}

三元组求最小距离

#define TNT 0x7fffff
int abc(int a){	//计算绝对值 
	if(a < 0)
		return -a;
	else
		return a;
}

bool min_xls( int a , int b ,int c ){	//看a是否是三个数的最小值 
	if(a <= b && a <= c )
		return true;
	return false; 
}

int findMinofTrip( int A[] , int n ,int B[] , int m ,int C[] , int p){
//D_min用来记录三元组最小距离,初值赋为TNT
	int i=0 , j=0 ,k=0 , D_min=TNT , D;
	while( i < n && j < m && k < p && D_min > 0){
		D = abc(A[i] - B[j]) + abc(B[j] - C[k]) + abc((C[k] + A[i]);	//计算D
		if( D < D_min )
			D_min = D;
		if( min_xls(A[i],B[j],C[k]))
			i++;	//更新a
		else if(min_xls(B[j],C[k],A[i])) 
			j++;
		else
			k++;
	}
	return D_min;
}

链表算法


递归形式删除相同x值

//递归形式,删除不带头结点的单链表了L中所有值为x的结点
void Delete_x(LinkList &L , int x){
	LNode*p;
	if(L == NULL)
		return;
	if(L->data == x){
		p = L;
		L=L->next;
		free(p);
		Delete_x(L,x);
	}
	else
		Delete_x(L->next , x);
} 

单链表删除x值

//一个个找下去,若是找到则删掉,找不到则往下一个 
void Delete_LNode_x(LinkList &L , int x){
	LNode *p=L->next , *pre = L , *q;
	while( p != NULL){
		if( p->data == x ){
			q = p;		//q指向该节点 
			p = p->next;	
			pre->next = p;	//删除q结点 
			free(q);		//释放*q结点的空间 
		}
		else{	//否则pre和p后移 
			pre = pre->next;
			p = p->next;
		} 
	}
}

单链表删除最小值的结点

//带头结点的单链表,删除最小值结点
LinkList Delete_Minnum( LinkList &L ){
	LNode *p = L->next , *pre = L;
	LNode *min = p , *minpre = pre;
	while( p != NULL){
		if( p->data < min->data ){
			min = p;	//找到比之前最小值还小的结点 
			minpre = pre;
		}
		pre = p;		//继续扫描下一个元素 
		p = pre->next;
	}
	pre->next= min->next;	//删除最小值 
	free(min);
	return L;
} 

单链表(就地!)逆置

//先断开头结点L,再将一个个后面的结点断开重新连接上头结点 
LinkList replacementList (LinkList L){
	LNode *p = L->next , *pre = p->next, *r;
    L->next =NULL;
	while( p->next != NULL){
		r = p->next;
		p->next = r->next;
		L->next = p;
		p = r;
	}
	return L;
} 

使元素递增有序

//运用插入排序思想
void Sort(LinkList &L){
	LNode *p = L->next,*pre;
	LNode *r = p->next;		//r保持在p之后,保证不断链
	p->next = NULL;			//将链表分为2条
	p = r;					
	while(p != NULL){
		r = p->next;
		pre = L;
		while(pre->next != NULL && pre->next->data < p->data)
			pre = pre->next;	//将有序表中查找插入*p的前驱结点*pre
		p->next = pre->next;	//将p插入在pre之后
		pre->next =p;			
		p = r;				//扫描剩下的结点
	}
}

删除给定X和Y数值间的元素

void RangeDelete(LinkList &L){
	LNode *p=L , *pre = p->next;
	while(p->next != NULL){
        if( p->next->data >x && p->next->data < y ){
            p->next = pre->next;
            free(p);
            p = p->next;
            pre = p->next;
        }
        else{
            p = p->next;
            pre = p->next;
        }
	}
}

找两个链表的公共节点

单链表中每个节点的next指针是唯一的,所以当存在公共节点的时候,其后面的所有节点也都是相同的,所以这是的链表是一个“Y”,而不是我们惯性思维想到的“X”。根据这个结论可知,如果两个链表存在公共节点的话,它们的尾结点也肯定是相同的。

//查找两个链表的公共节点
//两个链表的公共节点后面都是一样的 
//先找出两链表的长度差dist,再让其找到第一个结点
LNode* Search_SamNode(LinkList L1,LinkList L2){
    //获取两个链表的长度 dist表示长度差
    int len1 = Length(L1),len2 = Length(L2),dist;
    LNode* longptr,shortptr;
    if(len1 > len2){
        dist = len1 - len2;
        longptr = L1;
        shortptr = L2;
    }else{
        dist = len2 - len1;
        longptr = L2;
        shortptr = L1;
    }
    //将长指针后移dist,保证两个指针同步
    while(dist--)
        longptr = longptr->next;
    while(longptr != NULL){		//同步找到公共点
        if(longptr == shortptr)	//找到第一个公共节点
            return longptr;
        else{
            longptr = longptr->next;
            shortptr = shortptr->next;
        }
    }
    return NULL;
}

分解为2个链表

//将一个带头结点的链表按照奇偶位置分解成两个带头结点的链表
LinkList DepartList(LinkList &A){
    LinkList B;
    B = (LinkList)malloc(sizeof(LNode));
    int count = 1;
    //p为工作指针,q指向B头结点,y指向A头结点
    LNode *p = A->next,
          *q = B,
          *y = A;
    A->next = NULL;//将A链表置空
    while(p != NULL){
        if(count%2 == 0){//偶数位置添加到B的尾部
            q->next = p;
            q = p;
        }else{//奇数位置添加到A的尾部
            y->next = p;
            y = p;
        }
        p = p->next;//工作指针后移一位
        count++;//计数器加一
    }
    //将尾部指针指向空
    q->next = NULL;
    y->next = NULL;
    return B;
}

就地将C表变成AB两表

C:{a1,b1,a2,b2,a3,b3…an,bn};A:{a1,a2,a3…an};B:{b1,b2,b3…bn}

LinkList DisCreat(LinkList &A){
	LinkList &B;
	B = (LinkList)malloc(sizeof(LNode));
	B->next = NULL;
	LNode *p = A->next , *q;
	LNode *ra =A;
	while( p != NULL){
		ra->next = p;
		ra = p;
		p = p->next;
		if(p != NULL)
			q = p->next;
		p->next = B->next;
		B->next =p;
		p = q;
	}
	ra->next = NULL;
    return B;
}

顺序链表减去相同值

void Del_Same(LinkList &L){
//L为递增链表,减去链表中的相同值
	LNode *p = L->next ,*pre = p->next;
	if(p == NULL){
		return;
	}
	while(p->next != NULL){
		pre = p->next;
		if(p->data == pre->data){
			p->next =pre->next;
			free(pre);
		}
		else
			p = p->next;
	}
}

2个有序链表求交集

void Union(LinkList &L , LinkList &B){
	LNode *p = L->next , *pre = B->next,*r = L, *s = B;
	while( p != NULL){
		if(p->data == pre->next){
			s->next = pre->next;			
			pre->next = p->next;
			p->next = pre;
			pre = s->next;
			r = p;
			p = pre->next;
		}
		else if( p->data < pre->data){
			r = p;
			p = p->next;
		}
		else{
			r->next = pre->next;
			free(pre);
			pre = r->next;
		}
	}
	while (p){	//A没有遍历完 
		r = p;
		p = p->next;
	}
	while(pre){
		s = pre;
		pre = pre->next;
	}
	p->next = NULL;
	free(r);
	return;
}

判断是否是连续子序列

int pattern (LinkList A , LinkList B){
    LNode* p  = A;         //p为A链表的工作结点,本题假设A和B均无头结点
    LNode* pre  = A;    //记录每趟比较中A链表的开始结点
    LNode* q  = B;      //q是B链表的工作结点

    while( p && q ){
        if(p->data == q->data){
            p = p->next;
            q = q->next;
        }
        else{
            pre = pre->next ;   //A链表从上次开始比较结点的后继开始
            p = pre;
            q= B;
        }
    }
   
    if(q==NULL)  return 1;
    else return 0 ; 

双循环链表是否对称

void Symmetry (LinkList &L){
//从头扫描循环双链表,以判断链表是否对称
	LNode *p=L->next; *pre = L->prior;//两头工作指针
	while( p!= q && p->next != pre){
		if(p->data == pre->data){
			p = p->next;
			pre = pre->prior;
		}
		else
			return 0;
	}
	return 1;
}

链接两个循环双链表

LinkList Link(LinkList &h1,LinkList &h2){
    //将循环链表h2链接到循环链表h1之后,使之仍保持循环链表的形式
    LNode *p, *q;  //分别指向两个链表的尾结点
    p=h1;
    while (p->next!=h1)  //寻找 h1 的尾结点
        p=p->next;
    q=h2;
    while (q->next!=h2)  //寻找 h2 的尾结点
        q=q->next;
    p->next=h2;    //将h2链接到h1之后
    q->next=h1;    //令h2的尾结点指向h1
    return h1;
}

双链表找最小值并删除

void Del_All(LinkList &l){
	LNode *p , *pre, *minp ,*minpre;
//让minp指向最小值,minpre为其后缀,p,pre进行遍历 
	while(p! = L){
	//因为需要删除每一个元素,所以就需要重新遍历n次 
		p = L->next;
		pre = L;
		minp = p;
		minpre = pre;
	//让p和pre进行遍历与minp进行对比,找出最小值 
		while(p!= L){
			if(p->data < minp->data){
				minp = p;
				minpre = pre; 
			}
			pre = p;
			p = p->next;
		}
		printf("%d" , minp->data)data;//输出最小值 
		minpre->next = minp->next;//删除最小值 
		free(minp);//释放空间 
	}	
	free(L);
}

访问频度域freq的值的递减序排列

typedef struct LNode
{
    int data;
    struct LNode *pre;
    struct LNode *next;
    int freq;
}LNode,*LinkList;

void Locate(LinkList &L,int x)
{
    LNode* p = L->next , *q;
    while(p!=NULL){	//开始查找等于x的元素
        if(p->data==x)
           break;
        p=p->next;
    }
    if(p==NULL){
        printf("不存在值为x的结点");
        return 0;
    }
    else{
        p->freq++;
        LNode* temp=p;
        temp->next->pre=temp->pre;
        temp->pre->next=temp->next;//p点被摘下

        LNode* q=L->next;
        while(q!=NULL&&q->freq<p->freq)
            q=q->next;
        p->pre=q->pre;
        q->pre->next=p;	//将p节点插入,一定是排在同频率的第一个
        p->next=q;
        q->pre=p;
    }
    return L;
}

链表输出倒数结点的值

void Search_k(LinkList list , int k){
	LNode *p = list->link ,*q = list->link;
	int count= 0;	//利用count来进行计数 
	while( p != NULL){	//遍历到最后一个结点 
	//因为k为倒数,所以只用让p移动表长-k的长度就行 
		if(count <k)	//用count达到k大小来使p移动表长-k次 
			count++;
		else
			p = p->link;
			q = q->link;
	}
	if(count > k)
		return 0;
	else{
		printf("%d" ,q->data);
		return 1;
	}
}

判断链表是否有环

void *FindLoodStart(LinkList *head){
	LNode *p = head , *pre = head;
	//让p每次都比pre快走一步,这样如果存在环的话就p和pre就会在环里面相遇 
	while( p->next!= NULL && pre!= NULL){
		p = p->next;
		pre = pre->next->next;
		if(p == pre)
			break;
	}
	if( p->next ==NULL || pre == NULL)		//若是为NULL,则说明没有环 
		return NULL;
	LNode *q = head ,*r = p; 		//创立两个指针求出环的入口点 
	while( q!= NULL){
		q = q->next;
		r = r->next;
	}
	return q;		//返回入口点 	
} 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
考研复试是指在通过初试后,进入研究生招生复试环节。在考研复试中,学校通常会对考生进行面试和笔试等环节的考核,以综合评价考生的学术能力、综合素质和适应能力。下面是数据结构常见问题的介绍: 1. 数据结构的定义和作用是什么? 数据结构是指数据元素之间的关系,以及对这些关系进行操作的方法。它是计算机科学中非常重要的基础知识,用于组织和管理数据,提高数据的存储和检索效率。 2. 请介绍一下线性表和链表。 线性表是一种数据结构,其中数据元素之间存在一对一的关系。常见的线性表有顺序表链表顺序表使用连续的存储空间存储元素,可以通过下标直接访问元素;链表使用链式存储结构,每个节点包含数据和指向下一个节点的指针。 3. 请介绍一下栈和队列。 栈是一种特殊的线性表,只能在表尾进行插入和删除操作,遵循先进后出(LIFO)的原则。队列也是一种特殊的线性表,只能在表尾进行插入操作,在表头进行删除操作,遵循先进先出(FIFO)的原则。 4. 请介绍一下二叉树和二叉搜索树。 二叉树是一种特殊的树结构,每个节点最多有两个子节点。二叉搜索树是一种特殊的二叉树,对于任意节点,其左子树的值都小于该节点的值,右子树的值都大于该节点的值。 5. 请介绍一下图和图的表示方法。 图是由节点和边组成的一种非线性数据结构。节点表示图中的元素,边表示节点之间的关系。图的表示方法有邻接矩阵和邻接表两种常见方式。邻接矩阵使用二维数组表示节点之间的关系,邻接表使用链表数组表示节点和与之相邻的节点。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值