单链表
中心对称
- 单链表的表头指针为h,结点结构由data和next两个域构成,其中data域为字符型。写出算法dc(h,n),判断该链表的前n个字符是否中心对称。例如xyx,xyyx都是中心对称(2018)
int dc(LinkList h,int n){
char s[];
int i;
LinkList *p=h->next;
for(i=A;i<=n/B;i++){
s[i]=p->data;
p=p->next;
}
i--;
if(n%B==A) p=p->next;
while(p!=NULL && s[i]==p->data){
i--;
p=p->next;
}
if(p==NULL) return A;
else return 0;
}
插入无序列表的有序位置2
2.有一个数组中存放了一个无序的关键序列K1、K2、、Kn。现在要将Kn放在元素排序后的正确位置上,试编写算法,要求关键字比较次数不超过n(2015)
思路:快速排序以a[n]为哨兵
int partition (int a[],int low,int high,int n){
int pivot=a[n];
while(low<high){
while(low < high && a[low] <= pivotkey) low++;
a[high]=a[low];
while(low <high && a[high] >= pivotkey) high--;
a[low]=a[high];
}
a[high]=pivot;
return a[high];
}
删除最小结点2
3.在带头结点的单链表L中删除最小节点的高效算法(最小结点是唯一的)(2016)
正解:
访问前的结点p指向、temp指向最小值的结点,当前访问结点q,
设置min为最小值;
遍历q,如果q小于min,则min赋值;
void delMin(LinkList *L){
LinkList *p,*q,*temp;//temp指向最小值的结点
int min;
p=temp=L;
q=L->next;
min=q->val;
while(q){//找到最小结点
if(min > q->val){
min=q->val;
temp=q;
}
p=q;
q=q->next;
}
temp->next=p->next;
free(p);
}
顺序表前驱
4.实现顺序线性表基本操作获取一个数据元素的前驱 (2014)
正解:
status A1( SqList L,int cur_e,int &pre_e){
int i=1;
int *p=L.elem;
while(i<L.length&&*p!=curr_e){
i++;
p++;
}
if(i==L.length) return error;
else{
pre_e=*p;
return OK;
}
}
集合运算2
5.单链表实现集合运算:A=A-B(2013/2019)
//思路:双层遍历,把l2中和l1元素不相等的头插到l1
status Diff( LinkList &L1,LinkList &L2){
LinkList *p,*r,*q;
q=L2->next;
while(q){
p=L1->next;
r=L1;
while(p){
if(p->data==q->data){
r->next=p->next;//断开
free(p);
p=r->next;//l1的尾结点
}
else{
p=p->next;
q=q->next;
}
}
q=q->next;
}
}
删除值为x的元素2
6.(不带头结点)单链表,元素值均不同。删除单链表中值为x的数据元素,返回true/false(2012)
思路:就是判断L的元素值,通过r指向p的前驱,
当p的值为x时,r指向p的next并free(p)
bool delete(LinkList *L,int x){
LinkList *r,*p,*q;
p=L->next;
r=L;//r是p的前驱
if(L==NULL) return false;
if(L->data==x){
L->next=NULL;
free(p);
p=L;
return true;
}
while(p->next!=NULL){
if(p->data==x){
p->next=r->next;
free(p);
p=r->next;//这里p已经是原先被删除的结点的next了
return true;
}
else{
r=r->next;
p=p->next;
}
}
}
删除重复2
7.单链表删除重复节点(2019/2013)
正解:p为对照,s作为q前驱删除后继的重复结点
void del(LinkList *L){
LNode *p,*q,*s;
p=L->next;
for(p;p!=NULL;p=p->next){
s=p;
for(q=p->next;q!=NULL;){
if(q->val==p->val){
s->next=q->next;
free(q);
q=s->next;//原先被删除结点的next
}
else{//往后遍历
s=q;
q=q->next;
}
}
}
}
逆置
8.已经存在 顺序表 L1中所有数据元素逆置到新建的单链表(带头结点)(2010)
思路:
通过temp实现顺序表就地逆置;
将顺序表新建成单链表
void reverse(SqList &L1,LinkList &L2){
int temp,i=0;
for(int j=L1.length-1;i<j;++i;--j){//顺序表就地逆置
temp=L1[i];
L1[i]=L1[j];
L1[j]=temp;
}
LNode *p;
p=(LinkList*)malloc(sizeof(LinkList));
p->data=L1[0];
int x=i;
L2->next=p;//首节点L1[0]
while(x<L1.length){//遍历顺序表后插链表
q=(LinkList)malloc(sizeof(LinkList));
q->data=L1[x];
q->next=NULL;
p->next=q;
p=q;
}
}
单链表模拟栈
- 带头结点单链表实现链栈的初始化、入栈、出栈(2008)
void initstack(LinkStack &ls){
s=(LinkStack*)malloc(sizeof(LinkStack));
s->next=NULL;
return OK;
}
void pop(LinkStack *s,int e){
LinkStack *p;
s->next=p;
if(s->next==NULL)
return 1;
int x=p->data;
s->next=p->next;
free(p);
return 1;
}
void push(LinkStack *s,int e){
LinkStack *p;
p=(LinkList*)malloc (sizeof(LinkStack))
p->next==NULL;
s->next=p;
p->data=e;
p->next=s->next;
return ;
}
双向循环链表
- 带头结点的,按元素值递减有序的双向循环链表,插入一个元素保持有序性(2007)
status Insert(DuLinkList *L,int x){
DuLNode *p,p=L->next;
if(!L){//当链表为空,因为条件递减有序可以不用判断
s=(DuLinkList*) malloc(sizeof(DuLinkList));
L->next=s;
s->data=x;
s->next=NULL;
L->next=s->next;
}
while(p->data!=x)
p=p->next;
s=(DuLinkList*) malloc(sizeof(DuLinkList));
s->data=x;
p->next=s->next;
p->next=s;
s->next->prior=q;
s->prior=p;
return;
}
前插
- 线性表ai至ai+n-1共n个元素,插入到原表的第j个元素前(2006)
void A1(LinkList L,int i,int j, int n){
LNode *p,*q,*r,*s,*t,*u;
int k=1;p=L;
while(p!=NULL){
++K;
p=p->next;
if(k=i-1){
q=p;r=p->next;
}
if(k=i+n-1){
s=p;
}
if(k=j-i){
t=p;u=p->next;
}
}
q->next=s->next;
s->next=u;
t->next=r;
}
头插法
- 单链表所有负结点排在其他结点之后;保持非负结点间、负结点间相对次序(2005)
void ReLinkList(LinkList *L,int x){
LNode *p,*q;
int i=0;
p=L;
q=
while(p!=NULL){
if(p->next->data<0){
q->next=p->next;
p->next=p->next->next;
p=p->next;
++i;
}
else{
p=p->next;++i;
}
if(i>n){
q=NULL;break;;
}
}
}
就地逆置2
- 带头结点且仅设队尾指针的链式循环队列就地逆置(2004)
思路:找到front结点,重新设front的next为rear,从新的rear后面开始遍历,把每个结点插入到rear的前面
void reverse(LinkQueue *q){
QNode *front=q->rear->next;
if(front==rear){//空队列
return
}
QNode *p=front->next;
if(p->next==front){//只有1个元素
return
}
q->rear=p;//逆置后尾指针
p=p->next;
while(p!=front){//p的next依次插入front后面
QNode *temp=p;//temp是每次遍历要插入到前面的结点
p=p->next;
temp->next=front->next;
front->next=temp;
}
q->rear->next=q->front;最后一个插入的逆置指针和front相连
}
直接插入排序
14. 带头结点单链表直接插入排序(非递减)(2003/2011)
思路:
L->NULL q->p->u;
r指向L为头结点的链表的尾部;
当q<p
p、q指针往后移;
当q>p
u指向p的next,r->p->q
p指向u,继续q->p的遍历
void Insert(LinkList *L){
LinkList *p,*q,*r,*u;
p=L->next->next;
L->next->next=NULL;
while(p){
r=L;
q=L->next;
while(p && q->next && q->val<p->val){
r=q;
q=q->next;
}
u=p->next;
p->next=q;
r->next=p;
p=u;
}
return L->next;
}
//直接插入排序——顺序表
void insertionSort(int a[],int n){
int i,j;
for(int i=2;i<=n;i++){
if(a[i-1]>a[i]){
**a[0]=a[i];**
for(j=i-1;a[0]<a[j];--j){
a[j+1]=a[j];
}
a[j+1]=a[0];
}
}
}
- 顺序存储结构循环队列,写出入队出队算法(2001)
- 以为数组存放向量a,b, 互换位置把b放a前面(2001)