C语言链表定义及基本方法:
#include <stdio.h>
#define OK 1
#define ERROR 0
typedef int ElemType;
typedef int Status;
typedef struct Node{
ElemType data;
struct Node *next;
}Node;
typedef struct Node * LinkList;
// initialize
Status InitilizeList(LinkList *L){
*L = (LinkList)malloc(sizeof(Node)); // L is tou jie dian
if (*L == NULL) return ERROR; // why we need detect whether L is null???
(*L)->next = NULL;
return OK;
}
// print all element in linkedlist
Status ListTraverse(LinkList L){
LinkList p = L->next;
if (!p){
printf("the list is empty\n");
return ERROR;
}
while(p) {
printf(" %d ", p->data);
p = p->next;
}
printf("\n");
return OK;
}
// insert node into a linkedlist
Status ListInsert(LinkList *L, int i, ElemType e) {
int j;
LinkList p, s;
p = *L;
j = 1;
while(p && j<i) {
p = p->next;
++j;
}
if (!p || j>i) return ERROR; // why j>i
s = (LinkList)malloc(sizeof( Node));
s->data = e;
s->next = p->next;
p->next = s;
return 0;
}
- 将两个递增的有序链表合并为一个有序链表;要求结果链表仍然使用两个链表的存储空间,不另外占用其他的存储空间。表中不允许有重复的数据。(输入{1,2,3},{3,6,9}。 输出{1,2,3,6,9})
void mergeList(LinkList *La, LinkList *Lb, LinkList *Lc){
LinkList pa, pb, pc, temp;
pa = (*La)->next;
pb = (*Lb)->next;
*Lc = *La;
pc = *La;
while(pa && pb){
if(pa->data < pb->data){
pc->next = pa;
pc = pa;
pa = pa->next;
} else if(pa->data > pb->data){
pc->next = pb;
pc = pb;
pb = pb->next;
} else {
pc->next = pa;
pc = pa;
pa = pa->next;
temp = pb->next;
free(pb);
pb = temp;
}
}
pc->next = pa ? pa : pb;
free(*Lb);
}
- 已知两个链表A和B分别表示两个集合,其元素递增排列,设计一个算法,用于求出A与B的交集,并存储在A链表中
void Intersection(LinkList *La, LinkList *Lb, LinkList *Lc){
LinkList pa, pb, pc, temp;
pa = (*La)->next;
pb = (*Lb)->next;
*Lc = pc = *La;
while(pa && pb){
if(pa->data == pb->data){
pc->next = pa;
pc = pa;
pa = pa->next;
temp = pb;
pb = pb->next;
free(temp);
} else if(pa->data < pb->data){
temp = pa;
pa = pa->next;
free(temp);
} else {
temp = pb;
pb = pb->next;
free(temp);
}
}
pc->next = NULL;
while(pa){
temp = pa;
pa = pa->next;
free(temp);
}
while(pb){
temp = pb;
pb = pb->next;
free(temp);
}
}
3.设计一个算法,将链表中的所有节点的链接方向“原地旋转”, 要求仅仅利用原表的存储空间, 换句话说,要求算法空间复杂度为O(1)。
void reverseLinkList(LinkList *L){
LinkList p, q;
p = (*L)->next;
(*L)->next = NULL;
while(p){
q = p->next;
p->next = (*L)->next;
(*L)->next = p;
p = q;
}
}
- 设计一个算法,删除递增有序链表中值大于等于mink且小于等于maxk(mink, maxk是给定的两个参数, 其值可以和表中的元素相同,也可以不同)的所有元素。
void DeleteMinMax(LinkList *L, int mink, int maxk){
LinkList p, q, pre, temp;
pre = *L;
p = (*L)->next;
while(p && p->data < mink){
pre = p;
p = p->next;
}
while(p && p->data <= maxk){
p = p->next;
}
q = pre->next;
pre->next = p;
while(q!=p){
temp = q->next;
free(q);
q = temp;
}
}
- 设将n(n>1)个整数存放到一堆数组R中,试设计一个在时间和空间两方面都尽可能高效的算法;将R中保存的序列循环左移p(0<p<n)个位置,即将R中的数据由(x0, x1,......xn-1)变换为(xp, xp+1, ... , xn+1, x0, x1, ..., xp-1). 例如: pre[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, n = 10, p = 3; pre[10] = {3, 4, 5, 6, 7, 8, 9, 0, 1, 2} 思路: (1) n个数据原地逆置;{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, (2) 拆解; {9, 8, 7, 6, 5, 4, 3}{2, 1, 0} (3) n-p数据/p个数据 再一次逆置 {3 4 5 6 7 8 9}{0 1 2}
void Reverse(int *pre, int left, int right){
int i = left, j = right;
int temp;
while(i<j){
temp = pre[i];
pre[i] = pre[j];
pre[j] = temp;
i++;
j--;
}
}
void LefrShift(int *pre, int n, int p){
if(p>0 && p<n){
Reverse(pre, 0, n-1);
Reverse(pre, 0, n-p-1);
Reverse(pre, n-p, n-1);
}
}
- 已知一个整数序列A = (a0, a1, a2,...an-1), 其中(0<= ai <=n), (0<= i <=n). 若存在ap1 = ap2 =...= apm = x, 且m>n/2(0<= pk<n, 1<=k<=m), 则称x为A的主元素。例如,A=(0,5,5,3,5,7,5,5), 则5是主元素;若B=(0,5,5,3,5,1,5,7), 则A中没有主元素,假设A中的n个元素保存在一个一维数组中,请设计一个尽可能高效的算法,找出数组元素中的主元素,若存在主元素则输出该元素,否则输出-1。 思路: (1)选择候选主元素,循环计数方式找到链表哪个元素出现次数多!认为候选人 (2)判断到底是不是候选,候选人count > n/2
int MainElement(int *A, int n){
int count = 1;
int key = A[0];
for(int i=1; i<n; i++){
if(A[i] == key){
count++;
} else {
if(count>0){
count--;
}else {
key = A[i];
count = 1;
}
}
}
int total = 0;
for(int i=0; i<n; i++){
total = (A[i] == key) ? total+1 : total;
}
return (total > n/2) ? key : -1;
}
7.用单链表保存m个整数,结点的结构为(data,link),且|data|<=n(n为正整数)。 现在要去设计一个时间复杂度尽可能高效的算法。对于链表中的data绝对值相等的结点,仅保留第一次出现的结点,而删除其余绝对值相等的结点。例如:链表A={21,-15,15,-7,15},删除后的链表A={21,-15,-7}; 算法思路: (1)申请n+1辅助空间数组,初值设为零; (2)首元结点开始遍历,t[|data|],保留这个结点,t[|data|] = 1; 若t[|data|]=1, 删除;
void DeleteEqualNode(LinkList *L, int n){
int *p = alloca(sizeof(int)*(n+1));
LinkList r = *L;
for(int i=0; i<n+1; i++){
*(p+i) = 0;
}
LinkList temp = r->next;
while(temp != NULL){
if(p[abs(temp->data)] == 0){
p[abs(temp->data)] = 1;
r = temp;
temp = temp->next;
} else {
r->next = temp->next;
free(temp);
temp = r->next;
}
}
}